Compare commits

...

179 Commits

Author SHA1 Message Date
1e7572d0ea Merge branch 'release-2.3.2' of gitnex/GitNex into release-2.3 2019-12-25 19:25:38 +00:00
2e6d07860f prepare release 2.3.2 2019-12-26 00:22:22 +05:00
01498d6b0d Merge branch 'fix-234' of gitnex/GitNex into release-2.3 2019-12-25 19:11:03 +00:00
3e016dc90f fix double slash in url 2019-12-25 18:48:12 +05:00
52b65f8bed Merge branch 'backport-241' of gitnex/GitNex into release-2.3 2019-12-25 10:49:20 +00:00
e2b607d013 fix 2019-12-24 21:22:40 +01:00
82977c7a53 Merge branch 'releae-2.3.1' of gitnex/GitNex into release-2.3 2019-12-13 13:31:14 +00:00
9729ebdc99 prepare release 2.3.1 2019-12-13 18:13:19 +05:00
3ed5ddc6e8 Merge branch 'fix-file-decode-issue' of gitnex/GitNex into release-2.3 2019-12-13 13:07:25 +00:00
7019268512 fix decode filename 2019-12-13 13:52:18 +05:00
22b88bc4f4 Merge branch '231-revert-showing-only-issues' of gitnex/GitNex into release-2.3 2019-12-04 17:43:08 +00:00
b2565c7c62 show all in issues list, bump version 2019-12-04 21:16:41 +05:00
7d4ffe43dc Merge branch '223-copy-text-support-files' of gitnex/GitNex into release-2.3 2019-12-02 14:56:28 +00:00
3c12c9261d Merge branch '222-fix-alignments' of gitnex/GitNex into release-2.3 2019-12-02 14:45:17 +00:00
308bc033fa fix alignments 2019-12-02 13:08:01 +05:00
4fae271b09 allow copy, support more files 2019-12-01 23:57:46 +05:00
13a0b55612 Merge branch 'prepare-release-2.3' of gitnex/GitNex into master 2019-11-29 12:33:00 +00:00
94d4dbf440 add new sponsors 2019-11-29 17:31:19 +05:00
82034273c4 Crowdin [2019-11-29] + smal doc (#220) 2019-11-29 12:29:44 +00:00
cf22a5d5fa Merge branch 'allowRestrictedApi' of Unpublished/GitNex into master 2019-11-27 20:06:29 +00:00
fde33dbc3e Allow login if api is restricted 2019-11-27 20:27:31 +01:00
85a7fddc49 Merge branch '171-screens' of gitnex/GitNex into master 2019-11-27 18:05:55 +00:00
25fbc4b017 Add screens, update readme, f-droid desc 2019-11-27 22:55:09 +05:00
fc02b652f5 [Crowdin] 2019-11-27 + add Portuguese/Brazilian (#211) 2019-11-27 17:05:32 +00:00
a32e11c172 Merge branch '10-merge-pr' of gitnex/GitNex into master 2019-11-27 17:03:49 +00:00
51dc31ef15 merge pull request activity and call 2019-11-27 20:09:26 +05:00
5b4cb3ff8e Added interface and model 2019-11-25 19:19:13 +05:00
0daf0d1110 Merge branch '207-move-version-to-main-activity' of gitnex/GitNex into master 2019-11-25 13:14:33 +00:00
533be20f46 Move Gitea version to main activity 2019-11-25 18:12:44 +05:00
8b88dca833 Merge branch '205-refactor-version-code' of gitnex/GitNex into master 2019-11-25 13:06:52 +00:00
94d6334e52 refactor versions 2019-11-25 18:04:34 +05:00
79f6a2435b Crowdin [2019-11-25] + add Ukrainian (#204) 2019-11-25 12:12:11 +00:00
9f5eceff0e Repository PR List (#198) 2019-11-24 12:42:57 +00:00
f9550ad115 Merge branch '119-app-tokens' of gitnex/GitNex into master 2019-11-16 05:18:41 +00:00
7e8a2722ac Fix creating multiple tokens. The changes were from upstream API 2019-11-16 00:39:09 +05:00
51da8b9c4d Merge branch 'refactor-donate-credit-pages' of gitnex/GitNex into master 2019-11-14 17:00:24 +00:00
29fb2631cb refactored credit activtiy 2019-11-14 21:58:38 +05:00
126d1d0896 Refactor sponsors activity 2019-11-13 23:23:20 +05:00
b6c0e94ee9 Offline mode (#190) 2019-11-13 15:52:49 +00:00
80445952b1 Crowdin [2019-11-09] (#194) 2019-11-13 13:49:51 +00:00
d61fb8a0c6 Merge branch 'crowdin_2019-11-07' of gitnex/GitNex into master 2019-11-07 14:05:22 +00:00
51c88e9f45 update from crowdin 2019-11-07 13:31:35 +01:00
463961800f [File View] add highlight sourcecode (#187) 2019-11-05 08:34:22 +00:00
04073ac873 tocken name with Device ID (#184) 2019-11-01 06:01:30 +00:00
26b93a4280 Merge branch '182-fix-date-layout' of gitnex/GitNex into master 2019-10-31 14:29:48 +00:00
71be20b1b9 increase space for date and time 2019-10-31 18:23:36 +05:00
9f833259f7 Add limit to explore API 2019-10-31 18:16:11 +05:00
d184bdca12 Merge branch '175-fileview-support-images' of gitnex/GitNex into master 2019-10-30 18:00:03 +00:00
15b320f4bd Images support in file viewer. Android Q support. 2019-10-30 19:04:49 +05:00
fdc1514f5f Merge branch 'change-in-search-176' of gitnex/GitNex into master 2019-10-29 06:32:39 +00:00
67f4283cb9 Use search and magnify icon 2019-10-29 11:28:59 +05:00
fc2b09b91c Crowdin [2019-10-28] + Turkish support (#177) 2019-10-29 05:34:01 +00:00
eb38df745c Merge branch '94-login-via-token' of gitnex/GitNex into master 2019-10-26 18:38:58 +00:00
8787f8d9eb store loginUid on login 2019-10-26 18:01:14 +05:00
7e3eef90d2 radio buttons style to match the theme. error toast on failure 2019-10-25 23:19:16 +05:00
c4b0b596d3 fixes in fdroid repository description file 2019-10-25 10:55:00 +05:00
2aaf0eb103 refactor the strings and reuse them in login screen files 2019-10-25 08:38:35 +05:00
f9d51094e4 done with token logins, refactor some code 2019-10-24 22:42:09 +05:00
96ab992264 implement login via token 2019-10-24 20:48:00 +05:00
bc2b609585 Merge branch '166-improve-edit-button-api-calls' of gitnex/GitNex into master 2019-10-22 16:42:03 +00:00
2a05d4e24b improve edit button on tap 2019-10-22 21:37:11 +05:00
fb9d101283 Merge branch 'app-color-scheme' of gitnex/GitNex into master 2019-10-22 16:03:55 +00:00
ef2f5a9667 change color scheme 2019-10-22 21:00:55 +05:00
d14ecd9c68 Version Check before try to Login (#147) 2019-10-22 15:27:33 +00:00
d29b1901c0 Merge branch '158-fix-email-login' of gitnex/GitNex into master 2019-10-21 16:46:28 +00:00
6d7fcd8430 Fix login with email for my repositories 2019-10-21 20:39:42 +05:00
b6ca7bf2a4 Merge branch 'fix-empty-repo-bug' of gitnex/GitNex into master 2019-10-18 13:44:29 +00:00
24d56c625e Fix #154 2019-10-18 18:40:54 +05:00
67add714b3 Merge branch 'prepare-release-2.2' of gitnex/GitNex into master 2019-10-18 06:47:22 +00:00
5970995ef0 added file viewer 2019-10-18 10:28:18 +05:00
cf75c61704 release 2.2.0 2019-10-18 10:10:47 +05:00
8ac92a8b3c Merge branch '121-sub-dir-browsing' of gitnex/GitNex into master 2019-10-17 22:49:49 +00:00
f1f92ba494 make CI work 2019-10-18 00:46:19 +02:00
d7b1a226d0 implemented sub dir view 2019-10-17 22:47:27 +05:00
2bebe1e81d Merge branch 'crowdin_2019-10-17' of gitnex/GitNex into master 2019-10-17 15:54:59 +00:00
f5d560c601 Update Crowdin 2019-10-17 16:09:40 +02:00
d27000d481 Merge branch 'minor-fixes' of gitnex/GitNex into master 2019-10-17 13:57:55 +00:00
9aff1cb42a Minor ui fixes 2019-10-16 18:28:24 +05:00
7fe376fa44 Merge branch 'improve-ci' of gitnex/GitNex into master 2019-10-14 10:02:31 +00:00
6da4398369 dont run with empty task 2019-10-14 11:27:04 +02:00
dac0f690d8 more precise name 2019-10-14 11:06:46 +02:00
8a7031e7f5 Merge branch 'translation_add-Serbian' of 6543/GitNex into master 2019-10-14 05:11:31 +00:00
dd5f17d54d format code 2019-10-13 19:19:44 +02:00
505c930c32 first sr strings 2019-10-13 19:19:20 +02:00
edb6cdf154 add Serbian to Settings 2019-10-13 19:19:04 +02:00
687b66751f Merge branch 'crowdin_2019-10-13' of gitnex/GitNex into master 2019-10-13 12:51:24 +00:00
f14ae18324 Merge branch 'translation_add-Italian' of 6543/GitNex into master 2019-10-13 12:50:46 +00:00
ea52d6c6d2 dont run twice 2019-10-13 02:46:52 +02:00
40d12c3b97 Update Translation 2019-10-13 02:13:53 +02:00
32ebf31ef4 add first it strings 2019-10-13 02:08:46 +02:00
7fc4146c98 add Italian 2019-10-13 02:08:27 +02:00
e296a83aab Merge branch 'update-libs' of gitnex/GitNex into master 2019-10-12 17:13:43 +00:00
0fc7c67d0b update libs 2019-10-12 19:34:33 +05:00
143d680627 Merge branch '136-watch-a-repo' of gitnex/GitNex into master 2019-10-12 13:29:43 +00:00
69745b027e Implemented watch and unwatch a repository 2019-10-12 14:00:36 +05:00
7f3aed9bae fix star repo layout 2019-10-12 12:55:12 +05:00
5496401a77 Merge branch '130-star-a-repo' of gitnex/GitNex into master 2019-10-11 20:18:15 +00:00
4c0fd3c286 Implemented star/unstar a repository 2019-10-12 01:03:01 +05:00
40f924de2e Merge branch 'translation_add-Finnish' of 6543/GitNex into master 2019-10-11 19:24:49 +00:00
1953a9feff add Finnish 2019-10-11 20:14:59 +02:00
24c71b4beb Merge branch 'drone-rename-pipeline' of gitnex/GitNex into master 2019-10-11 18:08:52 +00:00
958606e476 add first strings 2019-10-11 20:07:50 +02:00
39d1007423 Drone Rename Pipeline
Rename Pipeline -> it does not loon nice and does not make sense
2019-10-11 18:02:40 +00:00
0e673bb256 Merge branch 'mentions' of 6543/GitNex into master 2019-10-11 16:53:11 +00:00
246ff6296a new line " " and italic 2019-10-11 18:34:22 +02:00
1d0b940c14 add sugestions + new translator 2019-10-11 18:15:19 +02:00
4d3fb54925 Merge branch 'lunny/add_ci_badge' of lunny/GitNex into master 2019-10-11 15:44:36 +00:00
cd81ff74bf add mentions 2019-10-11 16:57:53 +02:00
02843b4ca1 Add CI status badge on README 2019-10-11 13:15:05 +00:00
2189bd10bd Merge branch '100-bottomsheet-scroll' of gitnex/GitNex into master 2019-10-11 13:08:57 +00:00
35b9647709 improve bottomsheet with scroll and separater 2019-10-11 16:36:42 +05:00
2d2f486182 Merge branch '88-update-images' of gitnex/GitNex into master 2019-10-10 19:54:37 +00:00
640771d4fa update store images, update app description 2019-10-10 22:38:09 +05:00
2ba8a80b9f Merge branch 'repoSearch' of 6543/GitNex into master 2019-10-10 16:02:04 +00:00
2f55e7f5d1 enable to browse repository 2019-10-10 20:49:12 +05:00
d285115090 reset the adapter on new query 2019-10-10 19:01:15 +05:00
d5cffddc72 Implemented search ui and screen for exploring repositories. 2019-10-10 18:40:43 +05:00
9e2921697b Merge branch 'add-drone-ci' of gitnex/GitNex into master 2019-10-10 07:49:12 +00:00
e868364554 Merge branch 'crowdin_2019-10-10' of gitnex/GitNex into master 2019-10-10 07:48:27 +00:00
88a8303b1c Add Drone CI Config
* testing
       - test
       - build
2019-10-10 03:29:35 +02:00
ac1fc696ea complete france translation 2019-10-10 01:40:54 +02:00
2fe175223c combine commits
* add Explore Function
* define API
* Add Fragment + Code + String
* add to main activity (by @mmarif)
2019-10-10 01:21:34 +02:00
9cab502e84 Merge branch 'mv-org-update-links' of 6543/GitNex into master 2019-10-09 18:40:12 +00:00
88748998b3 update repo links 2019-10-09 16:09:07 +02:00
264ed393cb Merge branch 'readme-add-crowdin' of 6543/GitNex into master 2019-10-08 15:27:27 +00:00
821eef91a3 Merge branch 'crowdin_2019-10-07' of mmarif/GitNex into master 2019-10-08 15:26:56 +00:00
05afc9fc5a Merge branch 'crowdin-add-Persian' of 6543/GitNex into master 2019-10-08 15:26:18 +00:00
4cb6948288 Merge branch 'build-fix' of mmarif/GitNex into master 2019-10-08 14:48:28 +00:00
7012c2587c crowdin update 2019-10-08 02:54:18 +02:00
dbcbd076ea Build Fix 2019-10-08 02:41:39 +02:00
c633b62fdb show screenshots directly 2019-10-07 19:53:41 +02:00
1ce1a15955 mv Translation info (CONTRIBUTE -> README)
wil close https://gitea.com/mmarif/GitNex/issues/108
2019-10-07 19:53:30 +02:00
60b95e3c5d Add first Persian strings
got it from 243e53895b
2019-10-07 12:42:15 +02:00
48fb0cf91c add Persian to settings 2019-10-07 12:41:27 +02:00
8fcb05b0d2 Merge branch 'fixes' of mmarif/GitNex into master 2019-10-07 07:05:36 +00:00
074bbfe3cc Minor translation files fixes 2019-10-07 12:01:04 +05:00
84438b740a Merge branch '43-file-browser' of mmarif/GitNex into master 2019-10-07 06:32:42 +00:00
d4cd16a111 Merge branch 'master' into 43-file-browser 2019-10-07 11:26:24 +05:00
5ed053bba7 Merge branch 'crowdin-add-zh-CN' of mmarif/GitNex into master 2019-10-07 06:05:50 +00:00
598633a20a add first Chinese strings
@lunny thanks
2019-10-06 06:04:00 +02:00
8fe53dfd01 Settings: Languages: add Chinese and sort alphabetic 2019-10-06 06:01:48 +02:00
aadbcbd0c6 Merge branch 'crowdin-add-ar' into master 2019-10-04 19:25:53 +00:00
e3b901741a Add Untranslated Arabic 2019-10-04 20:56:29 +02:00
f8275cd7aa add Arabic to settings 2019-10-04 20:56:28 +02:00
c3afe1044c Merge branch 'crowdin' into master 2019-10-04 18:43:45 +00:00
a6503ba7c4 Crowdin Update 2019-10-04 20:26:20 +02:00
dddc9b0178 smal link fix for Translation 2019-10-04 20:24:44 +02:00
13bc50da40 git ignore crowdin config (crowdin.yml) 2019-10-04 20:23:43 +02:00
b32d291554 Merge branch 'translation-tool' of 6543/GitNex into master 2019-10-04 15:56:43 +00:00
c15e6e99f7 Added Arabic file 2019-10-04 20:46:56 +05:00
1512032f05 move corwdin Link to strings 2019-10-04 17:44:38 +02:00
e32ccde995 add info if lang is not listed 2019-10-04 16:55:09 +02:00
1be577cd3f add ClickListener to open Translation URL 2019-10-04 16:25:27 +02:00
7fa57621d9 change about layout 2019-10-04 16:20:46 +02:00
75ac6ff113 Add Crowdin Badge 2019-10-04 16:08:40 +02:00
9ef04b1287 change CONTRIBUTING.md for Crowdin 2019-10-04 16:08:17 +02:00
8c903b9658 remove some comments 2019-10-04 12:23:56 +05:00
08b8275546 translation files updates 2019-10-04 12:08:21 +05:00
5baacbd801 revert back 2019-10-04 00:21:34 +05:00
56b8b486df Merge branch 'release-2.1' into 43-file-browser 2019-10-04 00:06:03 +05:00
e4ab2f64fc wip, need clean up 2019-10-03 23:50:57 +05:00
345d577fbf Merge branch 'release-2.1' into 43-file-browser 2019-10-03 21:53:38 +05:00
5c9b53f5ab api interface for sub dirs
Signed-off-by: M M Arif <mmarif@swatian.com>
2019-10-03 21:32:09 +05:00
572f93d35c Idea to use breadcrumb 2019-10-03 20:57:49 +05:00
a77716970b update gradle 2019-10-03 12:15:55 +05:00
4d998150a3 click listener checks for file, dir and unknwon files 2019-10-02 23:32:01 +05:00
90df3a31fe Merge branch 'release-2.1' into 43-file-browser 2019-10-02 22:47:46 +05:00
0bcbca8bdc Fix crash from gplay console, app crash when no avatar url node is present in API. old gitea instances. 2019-10-02 22:11:10 +05:00
b90b3c3320 Added reading file contentts 2019-10-02 21:32:59 +05:00
21097da995 filter files and dirs 2019-10-02 18:21:44 +05:00
06b71586c1 Sort by folder 1st approach 2019-10-02 17:58:29 +05:00
d2213c0c14 new file icon 2019-10-02 13:59:34 +05:00
4c3b735534 translation updates 2019-10-02 13:35:14 +05:00
90dce6fff8 added layout, view models, adapter and fragment 2019-10-02 13:30:07 +05:00
d9337a24d3 Fixes since 2.1.0 release, ms progress bar fix, create issue enable fix 2019-10-01 22:45:21 +05:00
45ec660ba1 Merge branch 'master' into 43-file-browser 2019-10-01 21:23:03 +05:00
bb24254e66 added files model 2019-10-01 20:07:37 +05:00
13e69cd09b files tab in repo tabs 2019-10-01 19:48:20 +05:00
71839bcfd6 clean up 2019-10-01 19:35:51 +05:00
216 changed files with 11586 additions and 1820 deletions

31
.drone.yml Normal file
View File

@ -0,0 +1,31 @@
---
kind: pipeline
name: gitnex-ci-test
steps:
- name: test
image: nextcloudci/android:android-49
commands:
- ./gradlew test
trigger:
event:
- pull_request
---
kind: pipeline
name: gitnex-ci-build
steps:
- name: build
image: nextcloudci/android:android-49
commands:
- ./gradlew build
trigger:
event:
- push
branch:
- master

3
.gitignore vendored
View File

@ -180,6 +180,9 @@ crashlytics.properties
crashlytics-build.properties
fabric.properties
# Crowdin
crowdin.yml
### AndroidStudio Patch ###
!/gradle/wrapper/gradle-wrapper.jar

View File

@ -1,2 +1,2 @@
# Changelog
[Check out the release notes](https://gitea.com/mmarif/GitNex/releases)
[Check out the release notes](https://gitea.com/gitnex/GitNex/releases)

View File

@ -20,10 +20,3 @@ Before creating an issue please take a moment and search the repository issues(o
In case you want to submit a bug report, please provide as much details as possible to better debug the problem. The important part is how to reproduce the bug and steps to reproduce are appreciated.
**Note:** Please contact the project directly via email(gitnex@swatian.com) if have to share sensitive and security related details.
## Translation
Help us translate GitNex to your native language.
Take a look [here](https://gitea.com/mmarif/GitNex/src/branch/master/app/src/main/res/values/strings.xml) for strings, please ignore the lines with `translatable="false"`. It is recommended to create a Pull Request with your changes.
Check the structure of other languages for example [French](https://gitea.com/mmarif/GitNex/src/branch/master/app/src/main/res/values-fr/strings.xml).

35
CONTRIBUTORS.md Normal file
View File

@ -0,0 +1,35 @@
# Contributors
This part lists all PUBLIC individuals having contributed content to the code.
* M M Arif (mmarif)
* 6543
* Unpublished
# Translators
This part lists all PUBLIC individuals having contributed content to the translation.
*Entries are in alphabetical order*
* 6543
* acrylicpaintboy
* Antoine GIRARD (sapk)
* BaRaN6161_TURK
* ButterflyOfFire (BoFFire)
* dadosch
* erardiflorian
* IndeedNotJames
* jaqra
* ljoonal
* Lunny Xiao (xiaolunwen)
* lxs
* Marcos de Oliveira (markkrj)
* mmarif
* Nadezhda Moiseeva (digitalkiller)
* Oleg Popenkov (FanHamMer)
* PsychotherapistSam
* Rodion Borisov (vintproykt)
* s4ne
* valeriezhao1013
* Vladislav Glinsky (cl0ne)
* Voyvode
**Thank you for all your work** :+1:

View File

@ -1,5 +1,7 @@
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Release](https://img.shields.io/badge/dynamic/json.svg?label=release&url=https://gitea.com/api/v1/repos/mmarif/GitNex/releases&query=$[0].tag_name)](https://gitea.com/mmarif/GitNex/releases)
[![Release](https://img.shields.io/badge/dynamic/json.svg?label=release&url=https://gitea.com/api/v1/repos/gitnex/GitNex/releases&query=$[0].tag_name)](https://gitea.com/gitnex/GitNex/releases)
[![Build Status](https://drone.gitea.com/api/badges/gitnex/GitNex/status.svg)](https://drone.gitea.com/gitnex/GitNex)
[![Crowdin](https://badges.crowdin.net/gitnex/localized.svg)](https://crowdin.com/project/gitnex)
[<img alt="Become a Patroen" src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" height="40"/>](https://www.patreon.com/mmarif)
[<img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg" height="40"/>](https://liberapay.com/mmarif/donate)
@ -14,12 +16,12 @@ No trackers are used and source code is available here for anyone to audit.
## Downloads
[<img alt='Get it on F-droid' src='https://gitlab.com/fdroid/artwork/raw/master/badge/get-it-on.png' height="80"/>](https://f-droid.org/en/packages/org.mian.gitnex/)
[<img alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png' height="80"/>](https://play.google.com/store/apps/details?id=org.mian.gitnex)
[<img alt='Download APK' src='https://gitnex.com/img/download-apk.png' height="80"/>](https://gitea.com/mmarif/GitNex/releases)
[<img alt='Download APK' src='https://gitnex.com/img/download-apk.png' height="80"/>](https://gitea.com/gitnex/GitNex/releases)
## Note about Gitea version
Please make sure that you are on Gitea **1.9.x** stable release or later. Below this may not work as one would expect because of the newly added objects to the API at later versions. Please consider updating your Gitea server.
Please make sure that you are on Gitea **1.10.x** stable release or later. Below this may not work as one would expect because of the newly added objects to the API at later versions. Please consider updating your Gitea server.
Check the versions [compatibility page](https://gitea.com/mmarif/GitNex/wiki/Compatibility) which lists all the supported versions with compatibility ratio.
Check the versions [compatibility page](https://gitea.com/gitnex/GitNex/wiki/Compatibility) which lists all the supported versions with compatibility ratio.
## Build from source
Option 1 - Download the source code, open it in Android Studio and build it there.
@ -27,31 +29,43 @@ Option 1 - Download the source code, open it in Android Studio and build it ther
Option 2 - Open terminal(Linux) and cd to the project dir. Run `./gradlew build`.
## Features
- My Repositories
- Repositories list
- Organizations list
- Create repository
- Create organization
- File and directory browser
- Create files
- Explore repositories
- Issues list
- [MANY MORE](https://gitea.com/mmarif/GitNex/wiki/Features)
- Pull requests
- Merge pull request
- [MANY MORE](https://gitea.com/gitnex/GitNex/wiki/Features)
## Contributing
[CONTRIBUTING](https://gitea.com/mmarif/GitNex/src/branch/master/CONTRIBUTING.md)
[CONTRIBUTING](https://gitea.com/gitnex/GitNex/src/branch/master/CONTRIBUTING.md)
## Translation
Help us translate GitNex to your native language.
We use [Crowdin](https://crowdin.com/project/gitnex) for translation.
If your language is not listed, please request [here](https://gitea.com/gitnex/GitNex/issues) to add it to the project.
**Link: https://crowdin.com/project/GitNex**
## Screenshots:
[Screenshots](https://gitea.com/mmarif/GitNex/src/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots)
<img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/001.png" alt="001.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/002.png" alt="002.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/003.png" alt="003.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/004.png" alt="004.png" width="200"/>
---|---|---|---
<img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/005.png" alt="005.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/006.png" alt="006.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/007.png" alt="007.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/008.png" alt="008.png" width="200"/>
## FAQ
[Faq](https://gitea.com/mmarif/GitNex/wiki/FAQ)
[Faq](https://gitea.com/gitnex/GitNex/wiki/FAQ)
## Links
[Website](https://gitnex.com)
[Wiki](https://gitea.com/mmarif/GitNex/wiki/Home)
[Wiki](https://gitea.com/gitnex/GitNex/wiki/Home)
[Website Repository](https://gitlab.com/mmarif4u/gitnex-website)
[Troubleshoot Guide](https://gitea.com/mmarif/GitNex/wiki/Troubleshoot-Guide)
[Troubleshoot Guide](https://gitea.com/gitnex/GitNex/wiki/Troubleshoot-Guide)
## Thanks
Thanks to all the open source libraries, contributors and donators.
@ -69,5 +83,11 @@ Open source libraries
- Abumoallim/android-multi-select-dialog
- Pes/materialcolorpicker
- Hendraanggrian/socialview
- HamidrezaAmz/BreadcrumbsView
- Chrisbanes/PhotoView
- Pddstudio/highlightjs-android
- Apache/commons-io
- Caverock/androidsvg
- Droidsonroids.gif/android-gif-drawable
[Follow me on Fediverse - mastodon.social/@mmarif](https://mastodon.social/@mmarif)

View File

@ -1,13 +1,13 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
compileSdkVersion 29
defaultConfig {
applicationId "org.mian.gitnex"
minSdkVersion 21
targetSdkVersion 28
versionCode 63
versionName "2.1.3"
targetSdkVersion 29
versionCode 82
versionName "2.3.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@ -23,30 +23,29 @@ android {
}
dependencies {
def lifecycle_version = "2.2.0-alpha05"
final def markwon_version = "4.1.1"
def lifecycle_version = "2.2.0-rc02"
final def markwon_version = "4.1.1"
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.1.0-alpha10'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.github.vihtarb:tooltip:0.2.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.1'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.5.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.12.1'
implementation 'org.ocpsoft.prettytime:prettytime:4.0.1.Final'
implementation "androidx.appcompat:appcompat:1.1.0"
implementation "com.google.android.material:material:1.2.0-alpha02"
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
implementation "androidx.legacy:legacy-support-v4:1.0.0"
testImplementation "junit:junit:4.12"
androidTestImplementation "androidx.test:runner:1.2.0"
androidTestImplementation "androidx.test.espresso:espresso-core:3.2.0"
implementation "com.github.vihtarb:tooltip:0.2.0"
implementation "com.squareup.okhttp3:okhttp:3.12.1"
implementation "com.google.code.gson:gson:2.8.5"
implementation "com.squareup.picasso:picasso:2.71828"
implementation "com.amulyakhare:com.amulyakhare.textdrawable:1.0.1"
implementation "com.squareup.retrofit2:retrofit:2.5.0"
implementation "com.squareup.retrofit2:converter-gson:2.5.0"
implementation "com.squareup.retrofit2:converter-scalars:2.5.0"
implementation "com.squareup.okhttp3:logging-interceptor:3.12.1"
implementation "org.ocpsoft.prettytime:prettytime:4.0.1.Final"
implementation "com.vdurmont:emoji-java:4.0.0"
implementation "com.pes.materialcolorpicker:library:1.2.5"
implementation "io.noties.markwon:core:$markwon_version"
implementation "io.noties.markwon:ext-latex:$markwon_version"
implementation "io.noties.markwon:ext-strikethrough:$markwon_version"
@ -61,11 +60,13 @@ dependencies {
implementation "io.noties.markwon:simple-ext:$markwon_version"
implementation "io.noties.markwon:syntax-highlight:$markwon_version"
implementation "com.caverock:androidsvg:1.4"
implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.14"
implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.19"
implementation "com.hendraanggrian.appcompat:socialview:0.2"
implementation "com.hendraanggrian.appcompat:socialview-commons:0.2"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
implementation "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9"
implementation "commons-io:commons-io:2.6"
implementation "com.github.chrisbanes:PhotoView:2.3.0"
implementation "com.pddstudio:highlightjs-android:1.5.0"
}

View File

@ -2,6 +2,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mian.gitnex">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/app_logo"
@ -10,9 +13,13 @@
android:roundIcon="@mipmap/app_logo_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".activities.MergePullRequestActivity"></activity>
<activity
android:name=".activities.FileViewActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.NewFileActivity"
android:theme="@style/AppTheme.NoActionBar"></activity>
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.RepoWatchersActivity"
android:theme="@style/AppTheme.NoActionBar" />
@ -63,9 +70,7 @@
<activity android:name=".activities.NewRepoActivity" />
<activity android:name=".activities.NewOrganizationActivity" />
<activity android:name=".activities.OpenRepoInBrowserActivity" />
<activity android:name=".activities.FileDiffActivity" />
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@ -35,7 +35,7 @@ public class CollaboratorActions {
Call<Collaborators> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, context)
.getApiInterface()
.deleteCollaborator(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, userName);
@ -105,7 +105,7 @@ public class CollaboratorActions {
Call<Permission> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, context)
.getApiInterface()
.addCollaborator(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, userName, permissionString);

View File

@ -37,7 +37,7 @@ public class IssueActions {
Call<IssueComments> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, context)
.getApiInterface()
.patchIssueComment(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, commentId, commentBodyJson);
@ -104,7 +104,7 @@ public class IssueActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, context)
.getApiInterface()
.closeReopenIssue(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueStatJson);

View File

@ -0,0 +1,280 @@
package org.mian.gitnex.actions;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class RepositoryActions {
public static void starRepository(final Context context) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.starRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.isSuccessful()) {
if(response.code() == 204) {
tinyDb.putBoolean("repoCreated", true);
Toasty.info(context, context.getString(R.string.starRepositorySuccess));
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle),
context.getResources().getString(R.string.alertDialogTokenRevokedMessage),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
public static void unStarRepository(final Context context) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.unStarRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.isSuccessful()) {
if(response.code() == 204) {
tinyDb.putBoolean("repoCreated", true);
Toasty.info(context, context.getString(R.string.unStarRepositorySuccess));
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle),
context.getResources().getString(R.string.alertDialogTokenRevokedMessage),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
public static void watchRepository(final Context context) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.watchRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
tinyDb.putBoolean("repoCreated", true);
Toasty.info(context, context.getString(R.string.watchRepositorySuccess));
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle),
context.getResources().getString(R.string.alertDialogTokenRevokedMessage),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
public static void unWatchRepository(final Context context) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.unWatchRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 204) {
tinyDb.putBoolean("repoCreated", true);
Toasty.info(context, context.getString(R.string.unWatchRepositorySuccess));
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle),
context.getResources().getString(R.string.alertDialogTokenRevokedMessage),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
}

View File

@ -23,9 +23,9 @@ import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserSearch;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import java.util.Objects;
/**
* Author M M Arif
@ -46,8 +46,6 @@ public class AddCollaboratorToRepositoryActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_collaborator_to_repository);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
@ -81,7 +79,7 @@ public class AddCollaboratorToRepositoryActivity extends AppCompatActivity {
public void loadUserSearchList(String instanceUrl, String token, String searchKeyword, final Context context, String loginUid) {
Call<UserSearch> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getUserBySearch(Authorization.returnAuthentication(getApplicationContext(), loginUid, token), searchKeyword, 10);
@ -101,7 +99,7 @@ public class AddCollaboratorToRepositoryActivity extends AppCompatActivity {
@Override
public void onFailure(@NonNull Call<UserSearch> call, @NonNull Throwable t) {
Log.i("onFailure", t.getMessage());
Log.i("onFailure", t.toString());
}
});

View File

@ -65,7 +65,7 @@ public class AddRemoveAssigneesActivity extends AppCompatActivity {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
@ -90,7 +90,7 @@ public class AddRemoveAssigneesActivity extends AppCompatActivity {
// get current issue assignees
Call<Issues> callSingleIssueAssignees = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
@ -239,7 +239,7 @@ public class AddRemoveAssigneesActivity extends AppCompatActivity {
Call<JsonElement> call3;
call3 = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.patchIssueAssignee(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, updateAssigneeJson);

View File

@ -62,7 +62,7 @@ public class AddRemoveLabelsActivity extends AppCompatActivity {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getlabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
@ -87,7 +87,7 @@ public class AddRemoveLabelsActivity extends AppCompatActivity {
// get current issue labels
Call<List<Labels>> callSingleIssueLabels = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getIssueLabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
@ -249,7 +249,7 @@ public class AddRemoveLabelsActivity extends AppCompatActivity {
Labels patchIssueLabels = new Labels(issueLabels);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.updateIssueLabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, patchIssueLabels);

View File

@ -40,6 +40,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;
/**
* Author M M Arif
@ -217,7 +218,7 @@ public class CreateIssueActivity extends AppCompatActivity implements View.OnCli
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
@ -248,7 +249,7 @@ public class CreateIssueActivity extends AppCompatActivity implements View.OnCli
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.getMessage());
Log.i("onFailure", t.toString());
}
});
@ -261,7 +262,7 @@ public class CreateIssueActivity extends AppCompatActivity implements View.OnCli
Call<JsonElement> call3;
call3 = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewIssue(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, createNewIssueJson);
@ -325,7 +326,7 @@ public class CreateIssueActivity extends AppCompatActivity implements View.OnCli
String msState = "open";
Call<List<Milestones>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getMilestones(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, msState);
@ -339,13 +340,13 @@ public class CreateIssueActivity extends AppCompatActivity implements View.OnCli
List<Milestones> milestonesList_ = response.body();
milestonesList.add(new Milestones(0,"No milestone"));
milestonesList.add(new Milestones(0,getString(R.string.issueCreatedNoMilestone)));
assert milestonesList_ != null;
if(milestonesList_.size() > 0) {
for (int i = 0; i < milestonesList_.size(); i++) {
//String mStone = getString(R.string.spinnerMilestoneText, milestonesList_.get(i).getTitle(), milestonesList_.get(i).getState());
if(milestonesList_.get(i).getState().equals(getString(R.string.issueStatusOpen))) {
//Don't translate "open" is a enum
if(milestonesList_.get(i).getState().equals("open")) {
Milestones data = new Milestones(
milestonesList_.get(i).getId(),
milestonesList_.get(i).getTitle()
@ -379,7 +380,7 @@ public class CreateIssueActivity extends AppCompatActivity implements View.OnCli
private void getCollaborators(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
@ -449,7 +450,7 @@ public class CreateIssueActivity extends AppCompatActivity implements View.OnCli
private void getLabels(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getlabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);

View File

@ -28,6 +28,7 @@ import org.mian.gitnex.models.Labels;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.LabelsViewModel;
import java.util.Objects;
/**
* Author M M Arif
@ -55,9 +56,9 @@ public class CreateLabelActivity extends AppCompatActivity {
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(getIntent().getStringExtra("labelAction") != null && getIntent().getStringExtra("labelAction").equals("delete")) {
if(getIntent().getStringExtra("labelAction") != null && Objects.requireNonNull(getIntent().getStringExtra("labelAction")).equals("delete")) {
deleteLabel(instanceUrl, instanceToken, repoOwner, repoName, Integer.valueOf(getIntent().getStringExtra("labelId")), loginUid);
deleteLabel(instanceUrl, instanceToken, repoOwner, repoName, Integer.valueOf(Objects.requireNonNull(getIntent().getStringExtra("labelId"))), loginUid);
finish();
return;
@ -92,7 +93,7 @@ public class CreateLabelActivity extends AppCompatActivity {
}
});
if(getIntent().getStringExtra("labelAction") != null && getIntent().getStringExtra("labelAction").equals("edit")) {
if(getIntent().getStringExtra("labelAction") != null && Objects.requireNonNull(getIntent().getStringExtra("labelAction")).equals("edit")) {
labelName.setText(getIntent().getStringExtra("labelTitle"));
int labelColor_ = Color.parseColor("#" + getIntent().getStringExtra("labelColor"));
@ -242,7 +243,7 @@ public class CreateLabelActivity extends AppCompatActivity {
Call<CreateLabel> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createLabel(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, createLabelFunc);
@ -296,7 +297,7 @@ public class CreateLabelActivity extends AppCompatActivity {
Call<CreateLabel> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.patchLabel(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, labelId, createLabelFunc);
@ -369,7 +370,7 @@ public class CreateLabelActivity extends AppCompatActivity {
Call<Labels> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.deleteLabel(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, labelId);
@ -382,7 +383,7 @@ public class CreateLabelActivity extends AppCompatActivity {
if(response.code() == 204) {
Toasty.info(getApplicationContext(), getString(R.string.labelDeleteText));
LabelsViewModel.loadLabelsList(instanceUrl, instanceToken, repoOwner, repoName);
LabelsViewModel.loadLabelsList(instanceUrl, instanceToken, repoOwner, repoName, getApplicationContext());
getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId");

View File

@ -127,7 +127,7 @@ public class CreateNewUserActivity extends AppCompatActivity {
Call<UserInfo> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewUser(instanceToken, createUser);

View File

@ -164,7 +164,7 @@ public class CreateReleaseActivity extends AppCompatActivity {
Call<Releases> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewRelease(token, repoOwner, repoName, createReleaseJson);
@ -224,7 +224,7 @@ public class CreateReleaseActivity extends AppCompatActivity {
private void getBranches(String instanceUrl, String instanceToken, final String repoOwner, final String repoName) {
Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getBranches(instanceToken, repoOwner, repoName);

View File

@ -308,7 +308,7 @@ public class CreateTeamByOrgActivity extends AppCompatActivity implements View.O
Call<Teams> call3;
call3 = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createTeamsByOrg(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), orgName, createNewTeamJson);

View File

@ -1,12 +1,18 @@
package org.mian.gitnex.activities;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.CreditsAdapter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Author M M Arif
@ -22,14 +28,28 @@ public class CreditsActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_credits);
TextView creditKasun = findViewById(R.id.creditKasun);
ImageView closeActivity = findViewById(R.id.close);
creditKasun.setMovementMethod(LinkMovementMethod.getInstance());
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
Resources res = getResources();
CharSequence[] creditsInfo = res.getTextArray(R.array.creditsInfo);
List<CharSequence> creditsList = new ArrayList<>(Arrays.asList(creditsInfo));
RecyclerView mRecyclerView = findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
CreditsAdapter adapter = new CreditsAdapter(creditsList);
mRecyclerView.setAdapter(adapter);
}
private void initCloseListener() {

View File

@ -100,7 +100,13 @@ public class EditIssueActivity extends AppCompatActivity implements View.OnClick
editIssueButton.setOnClickListener(this);
if(!tinyDb.getString("issueNumber").isEmpty()) {
toolbar_title.setText(getString(R.string.editIssueNavHeader, String.valueOf(issueIndex)));
if(tinyDb.getString("issueType").equals("pr")) {
toolbar_title.setText(getString(R.string.editPrNavHeader, String.valueOf(issueIndex)));
}
else {
toolbar_title.setText(getString(R.string.editIssueNavHeader, String.valueOf(issueIndex)));
}
}
disableProcessButton();
@ -122,7 +128,7 @@ public class EditIssueActivity extends AppCompatActivity implements View.OnClick
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
@ -153,7 +159,7 @@ public class EditIssueActivity extends AppCompatActivity implements View.OnClick
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.getMessage());
Log.i("onFailure", t.toString());
}
});
@ -229,7 +235,7 @@ public class EditIssueActivity extends AppCompatActivity implements View.OnClick
CreateIssue issueData = new CreateIssue(title, description, dueDate, editIssueMilestoneId);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.patchIssue(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, issueData);
@ -240,7 +246,13 @@ public class EditIssueActivity extends AppCompatActivity implements View.OnClick
if(response.code() == 201) {
Toasty.info(getApplicationContext(), getString(R.string.editIssueSuccessMessage));
if(tinyDb.getString("issueType").equals("pr")) {
Toasty.info(getApplicationContext(), getString(R.string.editPrSuccessMessage));
}
else {
Toasty.info(getApplicationContext(), getString(R.string.editIssueSuccessMessage));
}
tinyDb.putBoolean("issueEdited", true);
tinyDb.putBoolean("resumeIssues", true);
finish();
@ -307,7 +319,7 @@ public class EditIssueActivity extends AppCompatActivity implements View.OnClick
private void getIssue(final String instanceUrl, final String instanceToken, final String loginUid, final String repoOwner, final String repoName, int issueIndex) {
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
@ -331,7 +343,7 @@ public class EditIssueActivity extends AppCompatActivity implements View.OnClick
if(response.body().getId() > 0) {
Call<List<Milestones>> call_ = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getMilestones(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, msState);

View File

@ -0,0 +1,212 @@
package org.mian.gitnex.activities;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.apache.commons.io.FilenameUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.FilesDiffAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.FileDiffView;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class FileDiffActivity extends AppCompatActivity {
private View.OnClickListener onClickListener;
private TextView toolbar_title;
private RecyclerView mRecyclerView;
private ProgressBar mProgressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_diff);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
toolbar_title = findViewById(R.id.toolbar_title);
mRecyclerView = findViewById(R.id.recyclerView);
mProgressBar = findViewById(R.id.progress_bar);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
toolbar_title.setText(R.string.processingText);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
mProgressBar.setVisibility(View.VISIBLE);
String fileDiffName = tinyDb.getString("issueNumber")+".diff";
getFileContents(tinyDb.getString("instanceUrlWithProtocol"), repoOwner, repoName, fileDiffName);
}
private void getFileContents(String instanceUrl, String owner, String repo, String filename) {
Call<ResponseBody> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getFileDiffContents(owner, repo, filename);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
if (response.code() == 200) {
try {
assert response.body() != null;
AppUtil appUtil = new AppUtil();
List<FileDiffView> fileContentsArray = new ArrayList<>();
String[] lines = response.body().string().split("diff");
if(lines.length > 0) {
for (int i = 1; i < lines.length; i++) {
if(lines[i].contains("@@ -")) {
String[] level2nd = lines[i].split("@@ -"); // main content part of single diff view
String[] fileName_ = level2nd[0].split("\\+\\+\\+ b/"); // filename part
String fileNameFinal = fileName_[1];
String[] fileContents_ = level2nd[1].split("@@"); // file info / content part
String fileInfoFinal = fileContents_[0];
String fileContentsFinal = (fileContents_[1]);
if(level2nd.length > 2) {
for (int j = 2; j < level2nd.length; j++) {
fileContentsFinal += (level2nd[j]);
}
}
String fileExtension = FilenameUtils.getExtension(fileNameFinal);
String fileContentsFinalWithBlankLines = fileContentsFinal.replaceAll( ".*@@.*", "" );
String fileContentsFinalWithoutBlankLines = fileContentsFinal.replaceAll( ".*@@.*(\r?\n|\r)?", "" );
fileContentsFinalWithoutBlankLines = fileContentsFinalWithoutBlankLines.replaceAll( ".*\\ No newline at end of file.*(\r?\n|\r)?", "" );
fileContentsArray.add(new FileDiffView(fileNameFinal, appUtil.imageExtension(fileExtension), fileInfoFinal, fileContentsFinalWithoutBlankLines));
}
else {
String[] getFileName = lines[i].split("--git a/");
String[] getFileName_ = getFileName[1].split("b/");
String getFileNameFinal = getFileName_[0].trim();
String[] binaryFile = getFileName_[1].split("GIT binary patch");
String binaryFileRaw = binaryFile[1].substring(binaryFile[1].indexOf('\n')+1);
String binaryFileFinal = binaryFile[1].substring(binaryFileRaw.indexOf('\n')+1);
String fileExtension = FilenameUtils.getExtension(getFileNameFinal);
fileContentsArray.add(new FileDiffView(getFileNameFinal, appUtil.imageExtension(fileExtension),"", binaryFileFinal));
}
}
}
int filesCount = fileContentsArray.size();
if(filesCount > 1) {
toolbar_title.setText(getResources().getString(R.string.fileDiffViewHeader, Integer.toString(filesCount)));
}
else {
toolbar_title.setText(getResources().getString(R.string.fileDiffViewHeaderSingle, Integer.toString(filesCount)));
}
FilesDiffAdapter adapter = new FilesDiffAdapter(fileContentsArray, getApplicationContext());
mRecyclerView.setAdapter(adapter);
mProgressBar.setVisibility(View.GONE);
} catch (IOException e) {
e.printStackTrace();
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(getApplicationContext(), getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(getApplicationContext(), getApplicationContext().getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(getApplicationContext(), getApplicationContext().getString(R.string.apiNotFound));
}
else {
Toasty.info(getApplicationContext(), getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
getIntent().removeExtra("singleFileName");
finish();
}
};
}
}

View File

@ -0,0 +1,205 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import com.github.chrisbanes.photoview.PhotoView;
import com.pddstudio.highlightjs.HighlightJsView;
import com.pddstudio.highlightjs.models.Theme;
import org.apache.commons.io.FilenameUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Files;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class FileViewActivity extends AppCompatActivity {
private View.OnClickListener onClickListener;
private TextView singleFileContents;
private HighlightJsView singleCodeContents;
private PhotoView imageView;
final Context ctx = this;
private ProgressBar mProgressBar;
private byte[] imageData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_view);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
singleFileContents = findViewById(R.id.singleFileContents);
singleCodeContents = findViewById(R.id.singleCodeContents);
imageView = findViewById(R.id.imageView);
singleFileContents.setVisibility(View.GONE);
mProgressBar = findViewById(R.id.progress_bar);
String singleFileName = getIntent().getStringExtra("singleFileName");
TextView toolbar_title = findViewById(R.id.toolbar_title);
toolbar_title.setMovementMethod(new ScrollingMovementMethod());
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
try {
singleFileName = URLDecoder.decode(singleFileName, "UTF-8");
singleFileName = singleFileName.replaceAll("//", "/");
singleFileName = singleFileName.startsWith("/") ? singleFileName.substring(1) : singleFileName;
}
catch (UnsupportedEncodingException e) {
assert singleFileName != null;
Log.i("singleFileName", singleFileName);
}
toolbar_title.setText(singleFileName);
getSingleFileContents(instanceUrl, instanceToken, repoOwner, repoName, singleFileName);
}
private void getSingleFileContents(String instanceUrl, String token, final String owner, String repo, final String filename) {
Call<Files> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getSingleFileContents(token, owner, repo, filename);
call.enqueue(new Callback<Files>() {
@Override
public void onResponse(@NonNull Call<Files> call, @NonNull retrofit2.Response<Files> response) {
if (response.code() == 200) {
AppUtil appUtil = new AppUtil();
assert response.body() != null;
if(!response.body().getContent().equals("")) {
String fileExtension = FilenameUtils.getExtension(filename);
mProgressBar.setVisibility(View.GONE);
if(appUtil.imageExtension(fileExtension)) { // file is image
singleFileContents.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
imageData = Base64.decode(response.body().getContent(), Base64.DEFAULT);
Drawable imageDrawable = new BitmapDrawable(getResources(), BitmapFactory.decodeByteArray(imageData, 0, imageData.length));
imageView.setImageDrawable(imageDrawable);
}
else if (appUtil.sourceCodeExtension(fileExtension)) { // file is sourcecode
imageView.setVisibility(View.GONE);
singleFileContents.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.VISIBLE);
singleCodeContents.setTheme(Theme.GRUVBOX_DARK);
singleCodeContents.setShowLineNumbers(true);
singleCodeContents.setSource(appUtil.decodeBase64(response.body().getContent()));
}
else { // file type not known - plain text view
imageView.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
singleFileContents.setVisibility(View.VISIBLE);
singleFileContents.setText(appUtil.decodeBase64(response.body().getContent()));
}
}
else {
singleFileContents.setText("");
mProgressBar.setVisibility(View.GONE);
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(getApplicationContext(), getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<Files> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
getIntent().removeExtra("singleFileName");
finish();
}
};
}
}

View File

@ -152,7 +152,7 @@ public class IssueDetailActivity extends AppCompatActivity {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
IssueCommentsViewModel.loadIssueComments(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
IssueCommentsViewModel.loadIssueComments(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, getApplicationContext());
}
}, 500);
}
@ -206,7 +206,7 @@ public class IssueDetailActivity extends AppCompatActivity {
scrollViewComments.post(new Runnable() {
@Override
public void run() {
IssueCommentsViewModel.loadIssueComments(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
IssueCommentsViewModel.loadIssueComments(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, getApplicationContext());
new Handler().postDelayed(new Runnable() {
@Override
@ -224,7 +224,7 @@ public class IssueDetailActivity extends AppCompatActivity {
scrollViewComments.post(new Runnable() {
@Override
public void run() {
IssueCommentsViewModel.loadIssueComments(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
IssueCommentsViewModel.loadIssueComments(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, getApplicationContext());
tinyDb.putBoolean("commentEdited", false);
}
});
@ -264,7 +264,7 @@ public class IssueDetailActivity extends AppCompatActivity {
IssueCommentsViewModel issueCommentsModel = ViewModelProviders.of(this).get(IssueCommentsViewModel.class);
issueCommentsModel.getIssueCommentList(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), owner, repo, index).observe(this, new Observer<List<IssueComments>>() {
issueCommentsModel.getIssueCommentList(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), owner, repo, index, getApplicationContext()).observe(this, new Observer<List<IssueComments>>() {
@Override
public void onChanged(@Nullable List<IssueComments> issueCommentsMain) {
adapter = new IssueCommentsAdapter(getApplicationContext(), issueCommentsMain);
@ -278,7 +278,7 @@ public class IssueDetailActivity extends AppCompatActivity {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);

View File

@ -1,9 +1,9 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.res.Resources;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
@ -15,21 +15,28 @@ import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import com.tooltip.Tooltip;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.VersionCheck;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.models.UserTokens;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.R;
import org.mian.gitnex.util.TinyDB;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import okhttp3.Credentials;
import okhttp3.Headers;
import retrofit2.Call;
import retrofit2.Callback;
@ -39,9 +46,13 @@ import retrofit2.Callback;
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
private Button login_button;
private EditText instance_url, login_uid, login_passwd, otpCode;
private Button loginButton;
private EditText instanceUrlET, loginUidET, loginPassword, otpCode, loginTokenCode;
private Spinner protocolSpinner;
private TextView otpInfo;
private RadioGroup loginMethod;
final Context ctx = this;
private String device_id = "token";
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -52,16 +63,19 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
TinyDB tinyDb = new TinyDB(getApplicationContext());
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
login_button = findViewById(R.id.login_button);
instance_url = findViewById(R.id.instance_url);
login_uid = findViewById(R.id.login_uid);
login_passwd = findViewById(R.id.login_passwd);
loginButton = findViewById(R.id.login_button);
instanceUrlET = findViewById(R.id.instance_url);
loginUidET = findViewById(R.id.login_uid);
loginPassword = findViewById(R.id.login_passwd);
otpCode = findViewById(R.id.otpCode);
otpInfo = findViewById(R.id.otpInfo);
ImageView info_button = findViewById(R.id.info);
final TextView viewTextGiteaVersion = findViewById(R.id.appVersion);
final TextView viewTextAppVersion = findViewById(R.id.appVersion);
protocolSpinner = findViewById(R.id.httpsSpinner);
loginMethod = findViewById(R.id.loginMethod);
loginTokenCode = findViewById(R.id.loginTokenCode);
viewTextGiteaVersion.setText(AppUtil.getAppVersion(getApplicationContext()));
viewTextAppVersion.setText(AppUtil.getAppVersion(getApplicationContext()));
Resources res = getResources();
String[] allProtocols = res.getStringArray(R.array.protocolValues);
@ -94,12 +108,31 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
}
loginMethod.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if(checkedId == R.id.loginUsernamePassword){
loginUidET.setVisibility(View.VISIBLE);
loginPassword.setVisibility(View.VISIBLE);
otpCode.setVisibility(View.VISIBLE);
otpInfo.setVisibility(View.VISIBLE);
loginTokenCode.setVisibility(View.GONE);
} else {
loginUidET.setVisibility(View.GONE);
loginPassword.setVisibility(View.GONE);
otpCode.setVisibility(View.GONE);
otpInfo.setVisibility(View.GONE);
loginTokenCode.setVisibility(View.VISIBLE);
}
}
});
//login_button.setOnClickListener(this);
if(!tinyDb.getString("instanceUrlRaw").isEmpty()) {
instance_url.setText(tinyDb.getString("instanceUrlRaw"));
instanceUrlET.setText(tinyDb.getString("instanceUrlRaw"));
}
if(!tinyDb.getString("loginUid").isEmpty()) {
login_uid.setText(tinyDb.getString("loginUid"));
loginUidET.setText(tinyDb.getString("loginUid"));
}
if(tinyDb.getBoolean("loggedInMode")) {
@ -109,20 +142,23 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
}
login_button.setOnClickListener(loginListener);
loginButton.setOnClickListener(loginListener);
if(!tinyDb.getString("uniqueAppId").isEmpty()) {
device_id = tinyDb.getString("uniqueAppId");
}
else {
device_id = UUID.randomUUID().toString();
tinyDb.putString("uniqueAppId", device_id);
}
}
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.login_button:
login();
break;
default:
if (v.getId() == R.id.login_button) {
login();
}
}
@ -131,7 +167,7 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
public void onClick(View v) {
disableProcessButton();
login_button.setText(R.string.processingText);
loginButton.setText(R.string.processingText);
login();
}
@ -159,112 +195,336 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
AppUtil appUtil = new AppUtil();
boolean connToInternet = AppUtil.haveNetworkConnection(LoginActivity.this);
String instanceUrl = instance_url.getText().toString().trim();
String loginUid = login_uid.getText().toString();
String loginPass = login_passwd.getText().toString();
String instanceUrl = instanceUrlET.getText().toString().trim();
String loginUid = loginUidET.getText().toString();
String loginPass = loginPassword.getText().toString();
String protocol = protocolSpinner.getSelectedItem().toString();
String loginOTP_ = otpCode.getText().toString().trim();
int loginMethodType = loginMethod.getCheckedRadioButtonId();
String loginToken_ = loginTokenCode.getText().toString().trim();
if(instanceUrl.contains("@")) {
if(loginMethodType == R.id.loginUsernamePassword) {
String[] urlForHttpAuth = instanceUrl.split("@");
if(instanceUrl.contains("@")) {
tinyDb.putString("basicAuthPassword", loginPass);
tinyDb.putBoolean("basicAuthFlag", true);
String[] urlForHttpAuth = instanceUrl.split("@");
instanceUrl = urlForHttpAuth[1];
loginUid = urlForHttpAuth[0];
tinyDb.putString("basicAuthPassword", loginPass);
tinyDb.putBoolean("basicAuthFlag", true);
}
String instanceHost;
if(AppUtil.httpCheck(instanceUrl)) {
URI uri = null;
try {
uri = new URI(instanceUrl);
} catch (URISyntaxException e) {
e.printStackTrace();
}
assert uri != null;
instanceHost = uri.getHost();
}
else {
instanceHost = instanceUrl;
}
String instanceUrlWithProtocol;
if(protocol.toLowerCase().equals("https")) {
instanceUrl = "https://" + instanceHost + "/api/v1/";
instanceUrlWithProtocol = "https://" + instanceHost;
}
else {
instanceUrl = "http://" + instanceHost + "/api/v1/";
instanceUrlWithProtocol = "https://" + instanceHost;
}
tinyDb.putString("instanceUrlRaw", instanceHost);
tinyDb.putString("loginUid", loginUid);
tinyDb.putString("instanceUrl", instanceUrl);
tinyDb.putString("instanceUrlWithProtocol", instanceUrlWithProtocol);
if(connToInternet) {
if(instance_url.getText().toString().equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emptyFieldURL));
enableProcessButton();
login_button.setText(R.string.btnLogin);
return;
}
if(loginUid.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emptyFieldUsername));
enableProcessButton();
login_button.setText(R.string.btnLogin);
return;
}
if(login_passwd.getText().toString().equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emptyFieldPassword));
enableProcessButton();
login_button.setText(R.string.btnLogin);
return;
instanceUrl = urlForHttpAuth[1];
loginUid = urlForHttpAuth[0];
}
int loginOTP = 0;
if(loginOTP_.length() == 6) {
String instanceHost;
if(AppUtil.httpCheck(instanceUrl)) {
if(appUtil.checkIntegers(loginOTP_)) {
loginOTP = Integer.valueOf(loginOTP_);
URI uri = null;
try {
uri = new URI(instanceUrl);
} catch (URISyntaxException e) {
e.printStackTrace();
}
else {
assert uri != null;
instanceHost = uri.getHost();
Toasty.info(getApplicationContext(), getString(R.string.loginOTPTypeError));
}
else {
instanceHost = instanceUrl;
}
String instanceUrlWithProtocol;
if(protocol.toLowerCase().equals("https")) {
instanceUrl = "https://" + instanceHost + "/api/v1/";
instanceUrlWithProtocol = "https://" + instanceHost;
}
else {
instanceUrl = "http://" + instanceHost + "/api/v1/";
instanceUrlWithProtocol = "https://" + instanceHost;
}
tinyDb.putString("instanceUrlRaw", instanceHost);
tinyDb.putString("loginUid", loginUid);
tinyDb.putString("instanceUrl", instanceUrl);
tinyDb.putString("instanceUrlWithProtocol", instanceUrlWithProtocol);
if(connToInternet) {
if(instanceUrlET.getText().toString().equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emptyFieldURL));
enableProcessButton();
login_button.setText(R.string.btnLogin);
loginButton.setText(R.string.btnLogin);
return;
}
if(loginUid.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emptyFieldUsername));
enableProcessButton();
loginButton.setText(R.string.btnLogin);
return;
}
if(loginPassword.getText().toString().equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emptyFieldPassword));
enableProcessButton();
loginButton.setText(R.string.btnLogin);
return;
}
}
int loginOTP = 0;
if(loginOTP_.length() == 6) {
letTheUserIn(instanceUrl, loginUid, loginPass, loginOTP);
if(appUtil.checkIntegers(loginOTP_)) {
loginOTP = Integer.valueOf(loginOTP_);
}
else {
Toasty.info(getApplicationContext(), getString(R.string.loginOTPTypeError));
enableProcessButton();
loginButton.setText(R.string.btnLogin);
return;
}
}
versionCheck(instanceUrl, loginUid, loginPass, loginOTP, loginToken_, 1);
}
else {
Toasty.info(getApplicationContext(), getString(R.string.checkNetConnection));
}
}
else {
Toasty.info(getApplicationContext(), getString(R.string.checkNetConnection));
String instanceHost;
if(AppUtil.httpCheck(instanceUrl)) {
URI uri = null;
try {
uri = new URI(instanceUrl);
} catch (URISyntaxException e) {
e.printStackTrace();
}
assert uri != null;
instanceHost = uri.getHost();
}
else {
instanceHost = instanceUrl;
}
String instanceUrlWithProtocol;
if(protocol.toLowerCase().equals("https")) {
instanceUrl = "https://" + instanceHost + "/api/v1/";
instanceUrlWithProtocol = "https://" + instanceHost;
}
else {
instanceUrl = "http://" + instanceHost + "/api/v1/";
instanceUrlWithProtocol = "https://" + instanceHost;
}
tinyDb.putString("instanceUrlRaw", instanceHost);
//tinyDb.putString("loginUid", loginUid);
tinyDb.putString("instanceUrl", instanceUrl);
tinyDb.putString("instanceUrlWithProtocol", instanceUrlWithProtocol);
if(connToInternet) {
if (instanceUrlET.getText().toString().equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emptyFieldURL));
enableProcessButton();
loginButton.setText(R.string.btnLogin);
return;
}
if (loginToken_.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.loginTokenError));
enableProcessButton();
loginButton.setText(R.string.btnLogin);
return;
}
versionCheck(instanceUrl, loginUid, loginPass, 123, loginToken_, 2);
}
else {
Toasty.info(getApplicationContext(), getString(R.string.checkNetConnection));
}
}
}
private void versionCheck(final String instanceUrl, final String loginUid, final String loginPass, final int loginOTP, final String loginToken_, final int loginType) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<GiteaVersion> callVersion = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getGiteaVersion();
callVersion.enqueue(new Callback<GiteaVersion>() {
@Override
public void onResponse(@NonNull final Call<GiteaVersion> callVersion, @NonNull retrofit2.Response<GiteaVersion> responseVersion) {
if (responseVersion.code() == 200) {
GiteaVersion version = responseVersion.body();
assert version != null;
VersionCheck vt = VersionCheck.check(getString(R.string.versionLow), getString(R.string.versionHigh), version.getVersion());
switch (vt) {
case UNSUPPORTED_NEW:
//Toasty.info(getApplicationContext(), getString(R.string.versionUnsupportedNew));
case SUPPORTED_LATEST:
case SUPPORTED_OLD:
case DEVELOPMENT:
login(loginType, instanceUrl, loginUid, loginPass, loginOTP, loginToken_);
return;
case UNSUPPORTED_OLD:
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(ctx, R.style.confirmDialog);
alertDialogBuilder
.setTitle(getString(R.string.versionAlertDialogHeader))
.setMessage(getResources().getString(R.string.versionUnsupportedOld, version.getVersion()))
.setCancelable(true)
.setIcon(R.drawable.ic_warning)
.setNegativeButton(getString(R.string.cancelButton), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
enableProcessButton();
}
})
.setPositiveButton(getString(R.string.textContinue), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
login(loginType, instanceUrl, loginUid, loginPass, loginOTP, loginToken_);
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
return;
default: // UNKNOWN
Toasty.info(getApplicationContext(), getString(R.string.versionUnknow));
enableProcessButton();
}
}
else if (responseVersion.code() == 403) {
login(loginType, instanceUrl, loginUid, loginPass, loginOTP, loginToken_);
}
}
private void login(int loginType, String instanceUrl, String loginUid, String loginPass, int loginOTP, String loginToken_) {
if (loginType == 1) {
letTheUserIn(instanceUrl, loginUid, loginPass, loginOTP);
}
else if (loginType == 2) { // token
letTheUserInViaToken(instanceUrl, loginToken_);
}
}
@Override
public void onFailure(@NonNull Call<GiteaVersion> callVersion, Throwable t) {
Log.e("onFailure-version", t.toString());
}
});
}
private void letTheUserInViaToken(String instanceUrl, final String loginToken_) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<UserInfo> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getUserInfo("token " + loginToken_);
call.enqueue(new Callback<UserInfo>() {
@Override
public void onResponse(@NonNull Call<UserInfo> call, @NonNull retrofit2.Response<UserInfo> response) {
UserInfo userDetails = response.body();
if (response.isSuccessful()) {
if (response.code() == 200) {
tinyDb.putBoolean("loggedInMode", true);
assert userDetails != null;
tinyDb.putString(userDetails.getLogin() + "-token", loginToken_);
tinyDb.putString("loginUid", userDetails.getLogin());
enableProcessButton();
loginButton.setText(R.string.btnLogin);
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
}
}
else if(response.code() == 401) {
String toastError = getResources().getString(R.string.unauthorizedApiError);
Toasty.info(getApplicationContext(), toastError);
enableProcessButton();
loginButton.setText(R.string.btnLogin);
}
else {
String toastError = getResources().getString(R.string.genericApiStatusError) + response.code();
Toasty.info(getApplicationContext(), toastError);
enableProcessButton();
loginButton.setText(R.string.btnLogin);
}
}
@Override
public void onFailure(@NonNull Call<UserInfo> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
Toasty.info(getApplicationContext(), getResources().getString(R.string.genericError));
enableProcessButton();
loginButton.setText(R.string.btnLogin);
}
});
}
private void letTheUserIn(final String instanceUrl, final String loginUid, final String loginPass, final int loginOTP) {
final String credential = Credentials.basic(loginUid, loginPass);
@ -272,13 +532,13 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
Call<List<UserTokens>> call;
if(loginOTP != 0) {
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getUserTokensWithOTP(credential, loginOTP, loginUid);
}
else {
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getUserTokens(credential, loginUid);
}
@ -290,7 +550,8 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
List<UserTokens> userTokens = response.body();
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Headers responseHeaders = response.headers();
final AppUtil appUtil = new AppUtil();
//Headers responseHeaders = response.headers();
if (response.isSuccessful()) {
@ -300,29 +561,46 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
assert userTokens != null;
if (userTokens.size() > 0) {
for (int i = 0; i < userTokens.size(); i++) {
if (userTokens.get(i).getSha1().equals(tinyDb.getString(loginUid + "-token"))) {
setTokenFlag = true;
break;
if(userTokens.get(0).getToken_last_eight() != null) {
for (int i = 0; i < userTokens.size(); i++) {
if (userTokens.get(i).getToken_last_eight().equals(tinyDb.getString(loginUid + "-token-last-eight"))) {
setTokenFlag = true;
break;
}
//Log.i("Tokens: ", userTokens.get(i).getToken_last_eight());
}
//Log.i("Tokens: ", userTokens.get(i).getSha1());
}
else {
for (int i = 0; i < userTokens.size(); i++) {
if (userTokens.get(i).getSha1().equals(tinyDb.getString(loginUid + "-token"))) {
setTokenFlag = true;
break;
}
//Log.i("Tokens: ", userTokens.get(i).getSha1());
}
}
}
if(tinyDb.getString(loginUid + "-token").isEmpty() || !setTokenFlag) {
UserTokens createUserToken = new UserTokens("gitnex-app-token");
UserTokens createUserToken = new UserTokens("gitnex-app-" + device_id);
Call<UserTokens> callCreateToken;
if(loginOTP != 0) {
callCreateToken = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewTokenWithOTP(credential, loginOTP, loginUid, createUserToken);
}
else {
callCreateToken = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewToken(credential, loginUid, createUserToken);
}
@ -332,7 +610,7 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
@Override
public void onResponse(@NonNull Call<UserTokens> callCreateToken, @NonNull retrofit2.Response<UserTokens> responseCreate) {
if (responseCreate.isSuccessful()) {
if(responseCreate.isSuccessful()) {
if(responseCreate.code() == 201) {
@ -345,6 +623,7 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
tinyDb.remove("loginPass");
tinyDb.putBoolean("loggedInMode", true);
tinyDb.putString(loginUid + "-token", newToken.getSha1());
tinyDb.putString(loginUid + "-token-last-eight", appUtil.getLastCharactersOfWord(newToken.getSha1(), 8));
//Log.i("Tokens", "new:" + newToken.getSha1() + " old:" + tinyDb.getString(loginUid + "-token"));
startActivity(new Intent(LoginActivity.this, MainActivity.class));
@ -357,10 +636,10 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
}
else if(responseCreate.code() == 500) {
String toastError = getResources().getString(R.string.genericApiStatusError) + String.valueOf(responseCreate.code());
String toastError = getResources().getString(R.string.genericApiStatusError) + responseCreate.code();
Toasty.info(getApplicationContext(), toastError);
enableProcessButton();
login_button.setText(R.string.btnLogin);
loginButton.setText(R.string.btnLogin);
}
@ -387,20 +666,20 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
}
else if(response.code() == 500) {
String toastError = getResources().getString(R.string.genericApiStatusError) + String.valueOf(response.code());
String toastError = getResources().getString(R.string.genericApiStatusError) + response.code();
Toasty.info(getApplicationContext(), toastError);
enableProcessButton();
login_button.setText(R.string.btnLogin);
loginButton.setText(R.string.btnLogin);
}
else {
String toastError = getResources().getString(R.string.genericApiStatusError) + String.valueOf(response.code());
String toastError = getResources().getString(R.string.genericApiStatusError) + response.code();
//Log.i("error message else4", String.valueOf(response.code()));
Toasty.info(getApplicationContext(), toastError);
enableProcessButton();
login_button.setText(R.string.btnLogin);
loginButton.setText(R.string.btnLogin);
}
@ -411,7 +690,7 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
Log.e("onFailure-login", t.toString());
Toasty.info(getApplicationContext(), getResources().getString(R.string.malformedJson));
enableProcessButton();
login_button.setText(R.string.btnLogin);
loginButton.setText(R.string.btnLogin);
}
});
@ -419,21 +698,21 @@ public class LoginActivity extends AppCompatActivity implements View.OnClickList
private void disableProcessButton() {
login_button.setEnabled(false);
loginButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
login_button.setBackground(shape);
loginButton.setBackground(shape);
}
private void enableProcessButton() {
login_button.setEnabled(true);
loginButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
login_button.setBackground(shape);
loginButton.setBackground(shape);
}

View File

@ -21,6 +21,7 @@ import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.AboutFragment;
import org.mian.gitnex.fragments.ExploreRepositoriesFragment;
import org.mian.gitnex.fragments.MyRepositoriesFragment;
import org.mian.gitnex.fragments.NavSubMenuBottomSheetFragment;
import org.mian.gitnex.fragments.OrganizationsFragment;
@ -29,6 +30,7 @@ import org.mian.gitnex.fragments.StarredRepositoriesFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
@ -123,41 +125,40 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
@Override
public void onDrawerOpened(@NonNull View drawerView) {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
if(!connToInternet) {
if(!tinyDb.getBoolean("noConnection")) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
}
tinyDb.putBoolean("noConnection", true);
String userEmailNav = tinyDb.getString("userEmail");
String userFullNameNav = tinyDb.getString("userFullname");
String userAvatarNav = tinyDb.getString("userAvatar");
userEmail = hView.findViewById(R.id.userEmail);
if (!userEmailNav.equals("")) {
userEmail.setText(userEmailNav);
}
userFullName = hView.findViewById(R.id.userFullname);
if (!userFullNameNav.equals("")) {
userFullName.setText(userFullNameNav);
}
userAvatar = hView.findViewById(R.id.userAvatar);
if (!userAvatarNav.equals("")) {
Picasso.get().load(userAvatarNav).networkPolicy(NetworkPolicy.OFFLINE).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(userAvatar);
}
} else {
displayUserInfo(instanceUrl, instanceToken, loginUid);
if(tinyDb.getBoolean("noConnection")) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
tinyDb.putBoolean("noConnection", false);
}
//tinyDb.putBoolean("noConnection", true);
String userEmailNav = tinyDb.getString("userEmail");
String userFullNameNav = tinyDb.getString("userFullname");
String userAvatarNav = tinyDb.getString("userAvatar");
userEmail = hView.findViewById(R.id.userEmail);
if (!userEmailNav.equals("")) {
userEmail.setText(userEmailNav);
}
userFullName = hView.findViewById(R.id.userFullname);
if (!userFullNameNav.equals("")) {
userFullName.setText(userFullNameNav);
}
userAvatar = hView.findViewById(R.id.userAvatar);
if (!userAvatarNav.equals("")) {
Picasso.get().load(userAvatarNav).networkPolicy(NetworkPolicy.OFFLINE).transform(new RoundedTransformation(8, 0)).resize(160, 160).centerCrop().into(userAvatar);
}
userAvatar.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ProfileFragment()).commit();
drawer.closeDrawers();
}
});
}
@Override
@ -217,6 +218,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
} else {
displayUserInfo(instanceUrl, instanceToken, loginUid);
giteaVersion(instanceUrl);
tinyDb.putBoolean("noConnection", false);
}
@ -278,6 +280,11 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new StarredRepositoriesFragment()).commit();
break;
case R.id.nav_explore:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ExploreRepositoriesFragment()).commit();
break;
}
drawer.closeDrawer(GravityCompat.START);
@ -306,12 +313,48 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
}
private void giteaVersion(final String instanceUrl) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<GiteaVersion> callVersion = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getGiteaVersion();
callVersion.enqueue(new Callback<GiteaVersion>() {
@Override
public void onResponse(@NonNull final Call<GiteaVersion> callVersion, @NonNull retrofit2.Response<GiteaVersion> responseVersion) {
if (responseVersion.code() == 200) {
GiteaVersion version = responseVersion.body();
assert version != null;
tinyDb.putString("giteaVersion", version.getVersion());
}
}
@Override
public void onFailure(@NonNull Call<GiteaVersion> callVersion, Throwable t) {
Log.e("onFailure-version", t.toString());
}
});
}
private void displayUserInfo(String instanceUrl, String token, String loginUid) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<UserInfo> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getUserInfo(Authorization.returnAuthentication(getApplicationContext(), loginUid, token));
@ -339,7 +382,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
tinyDb.putString("userFullname", userDetails.getFullname());
}
else {
tinyDb.putString("userFullname", "...");
tinyDb.putString("userFullname", userDetails.getLogin());
}
tinyDb.putString("userEmail", userDetails.getEmail());
@ -354,9 +397,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
userAvatar = hView.findViewById(R.id.userAvatar);
if (!Objects.requireNonNull(userDetails).getAvatar().equals("")) {
Picasso.get().load(userDetails.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(userAvatar);
Picasso.get().load(userDetails.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(160, 160).centerCrop().into(userAvatar);
} else {
userAvatar.setImageResource(R.mipmap.ic_launcher_round);
userAvatar.setImageResource(R.mipmap.app_logo_round);
}
userFullName = hView.findViewById(R.id.userFullname);

View File

@ -0,0 +1,258 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.MergePullRequest;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class MergePullRequestActivity extends AppCompatActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
final Context ctx = this;
private SocialAutoCompleteTextView mergePR;
private ArrayAdapter<Mention> defaultMentionAdapter;
private Button mergeButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_merge_pull_request);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
mergePR = findViewById(R.id.mergePR);
mergePR.setShowSoftInputOnFocus(true);
defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList();
mergePR.setMentionAdapter(defaultMentionAdapter);
closeActivity = findViewById(R.id.close);
TextView toolbar_title = findViewById(R.id.toolbar_title);
if(!tinyDb.getString("issueTitle").isEmpty()) {
toolbar_title.setText(tinyDb.getString("issueTitle"));
}
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
mergeButton = findViewById(R.id.mergeButton);
if(!connToInternet) {
disableProcessButton();
} else {
mergeButton.setOnClickListener(mergePullRequest);
}
}
public void loadCollaboratorsList() {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
String fullName = "";
for (int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(
new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
}
else {
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.toString());
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private View.OnClickListener mergePullRequest = new View.OnClickListener() {
public void onClick(View v) {
processMergePullRequest();
}
};
private void processMergePullRequest() {
String mergePRDT = mergePR.getText().toString();
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
disableProcessButton();
String doWhat = "merge";
mergeFunction(doWhat, mergePRDT);
}
private void mergeFunction(String doWhat, String mergePRDT) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int prIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
MergePullRequest mergePR = new MergePullRequest(doWhat, mergePRDT, null);
Call<ResponseBody> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.mergePullRequest(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, prIndex, mergePR);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
if(response.code() == 200) {
Toasty.info(getApplicationContext(), getString(R.string.mergePRSuccessMsg));
tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.mergePR404ErrorMsg));
}
else {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void disableProcessButton() {
mergeButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
mergeButton.setBackground(shape);
}
private void enableProcessButton() {
mergeButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
mergeButton.setBackground(shape);
}
}

View File

@ -204,7 +204,7 @@ public class NewFileActivity extends AppCompatActivity {
}
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewFile(token, repoOwner, repoName, fileName, createNewFileJsonStr);
@ -256,7 +256,7 @@ public class NewFileActivity extends AppCompatActivity {
private void getBranches(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getBranches(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);

View File

@ -137,7 +137,7 @@ public class NewMilestoneActivity extends AppCompatActivity implements View.OnCl
Call<Milestones> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createMilestone(token, repoOwner, repoName, createMilestone);

View File

@ -134,7 +134,7 @@ public class NewOrganizationActivity extends AppCompatActivity {
UserOrganizations createOrganization = new UserOrganizations(orgName, null, orgDesc, null, null);
Call<UserOrganizations> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewOrganization(token, createOrganization);

View File

@ -162,7 +162,7 @@ public class NewRepoActivity extends AppCompatActivity {
if(repoOwner.equals(loginUid)) {
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewUserRepository(token, createRepository);
@ -170,7 +170,7 @@ public class NewRepoActivity extends AppCompatActivity {
else {
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewUserOrgRepository(token, repoOwner, createRepository);
@ -225,7 +225,7 @@ public class NewRepoActivity extends AppCompatActivity {
private void getOrgs(String instanceUrl, String instanceToken, final String userLogin) {
Call<List<OrgOwner>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getOrgOwners(instanceToken);

View File

@ -72,7 +72,7 @@ public class OrgTeamMembersActivity extends AppCompatActivity {
TeamMembersByOrgViewModel teamMembersModel = new ViewModelProvider(this).get(TeamMembersByOrgViewModel.class);
teamMembersModel.getMembersByOrgList(instanceUrl, instanceToken, teamId).observe(this, new Observer<List<UserInfo>>() {
teamMembersModel.getMembersByOrgList(instanceUrl, instanceToken, teamId, getApplicationContext()).observe(this, new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> teamMembersListMain) {
adapter = new TeamMembersByOrgAdapter(getApplicationContext(), teamMembersListMain);

View File

@ -114,7 +114,7 @@ public class ProfileEmailActivity extends AppCompatActivity {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.addNewEmail(token, addEmailFunc);

View File

@ -83,6 +83,7 @@ public class ReplyToIssueActivity extends AppCompatActivity {
replyButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
disableProcessButton();
IssueActions.editIssueComment(ctx, Integer.valueOf(commentId), addComment.getText().toString());
}
@ -117,7 +118,7 @@ public class ReplyToIssueActivity extends AppCompatActivity {
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
@ -211,7 +212,7 @@ public class ReplyToIssueActivity extends AppCompatActivity {
Issues issueComment = new Issues(newReplyDT);
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.replyCommentToIssue(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, issueComment);
@ -225,6 +226,7 @@ public class ReplyToIssueActivity extends AppCompatActivity {
Toasty.info(getApplicationContext(), getString(R.string.commentSuccess));
tinyDb.putBoolean("commentPosted", true);
tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("resumePullRequests", true);
finish();
}

View File

@ -1,6 +1,7 @@
package org.mian.gitnex.activities;
import com.google.android.material.tabs.TabLayout;
import com.google.gson.JsonElement;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
@ -26,14 +27,17 @@ import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BranchesFragment;
import org.mian.gitnex.fragments.ClosedIssuesFragment;
import org.mian.gitnex.fragments.CollaboratorsFragment;
import org.mian.gitnex.fragments.FilesFragment;
import org.mian.gitnex.fragments.IssuesFragment;
import org.mian.gitnex.fragments.LabelsFragment;
import org.mian.gitnex.fragments.MilestonesFragment;
import org.mian.gitnex.fragments.PullRequestsFragment;
import org.mian.gitnex.fragments.ReleasesFragment;
import org.mian.gitnex.fragments.RepoBottomSheetFragment;
import org.mian.gitnex.fragments.RepoInfoFragment;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchRepository;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.Objects;
@ -87,15 +91,18 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
if(!tinyDb.getString("issuesCounter").isEmpty()) {
getRepoInfo(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName1);
}
Objects.requireNonNull(tabLayout.getTabAt(1)).setCustomView(tabHeader);
Objects.requireNonNull(tabLayout.getTabAt(2)).setCustomView(tabHeader);
TabLayout.Tab tabOpenIssues = tabLayout.getTabAt(1);
TabLayout.Tab tabOpenIssues = tabLayout.getTabAt(2);
ColorStateList textColor = tabLayout.getTabTextColors();
assert tabOpenIssues != null;
TextView openIssueTabView = Objects.requireNonNull(tabOpenIssues.getCustomView()).findViewById(R.id.counterBadgeText);
openIssueTabView.setTextColor(textColor);
}
checkRepositoryStarStatus(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName1);
checkRepositoryWatchStatus(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName1);
}
@Override
@ -199,21 +206,26 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
switch (position) {
case 0: // information
return RepoInfoFragment.newInstance(repoOwner, repoName);
case 1: // issues
case 1: // files
return FilesFragment.newInstance(repoOwner, repoName);
case 2: // issues
fragment = new IssuesFragment();
break;
case 2: // closed issues
case 3: // closed issues
fragment = new ClosedIssuesFragment();
break;
case 3: // milestones
case 4: // pull requests
fragment = new PullRequestsFragment();
break;
case 5: // milestones
return MilestonesFragment.newInstance(repoOwner, repoName);
case 4: // labels
case 6: // labels
return LabelsFragment.newInstance(repoOwner, repoName);
case 5: // branches
case 7: // branches
return BranchesFragment.newInstance(repoOwner, repoName);
case 6: // releases
case 8: // releases
return ReleasesFragment.newInstance(repoOwner, repoName);
case 7: // collaborators
case 9: // collaborators
return CollaboratorsFragment.newInstance(repoOwner, repoName);
}
return fragment;
@ -221,7 +233,7 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
@Override
public int getCount() {
return 8;
return 10;
}
}
@ -229,7 +241,7 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
private void getRepoInfo(String instanceUrl, String token, final String owner, String repo) {
Call<UserRepositories> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getUserRepository(token, owner, repo);
@ -264,4 +276,67 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
}
private void checkRepositoryStarStatus(String instanceUrl, String instanceToken, final String owner, String repo) {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.checkRepoStarStatus(instanceToken, owner, repo);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putInt("repositoryStarStatus", response.code());
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void checkRepositoryWatchStatus(String instanceUrl, String instanceToken, final String owner, String repo) {
Call<WatchRepository> call;
call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.checkRepoWatchStatus(instanceToken, owner, repo);
call.enqueue(new Callback<WatchRepository>() {
@Override
public void onResponse(@NonNull Call<WatchRepository> call, @NonNull retrofit2.Response<WatchRepository> response) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
if(response.code() == 200) {
assert response.body() != null;
if(response.body().getSubscribed()) {
tinyDb.putBoolean("repositoryWatchStatus", true);
}
}
else {
tinyDb.putBoolean("repositoryWatchStatus", false);
}
}
@Override
public void onFailure(@NonNull Call<WatchRepository> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
}

View File

@ -64,7 +64,7 @@ public class RepoStargazersActivity extends AppCompatActivity {
RepoStargazersViewModel repoStargazersModel = new ViewModelProvider(this).get(RepoStargazersViewModel.class);
repoStargazersModel.getRepoStargazers(instanceUrl, instanceToken, repoOwner, repoName).observe(this, new Observer<List<UserInfo>>() {
repoStargazersModel.getRepoStargazers(instanceUrl, instanceToken, repoOwner, repoName, getApplicationContext()).observe(this, new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> stargazersListMain) {
adapter = new RepoStargazersAdapter(getApplicationContext(), stargazersListMain);

View File

@ -64,7 +64,7 @@ public class RepoWatchersActivity extends AppCompatActivity {
RepoWatchersViewModel repoWatchersModel = new ViewModelProvider(this).get(RepoWatchersViewModel.class);
repoWatchersModel.getRepoWatchers(instanceUrl, instanceToken, repoOwner, repoName).observe(this, new Observer<List<UserInfo>>() {
repoWatchersModel.getRepoWatchers(instanceUrl, instanceToken, repoOwner, repoName, getApplicationContext()).observe(this, new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> watchersListMain) {
adapter = new RepoWatchersAdapter(getApplicationContext(), watchersListMain);

View File

@ -1,12 +1,18 @@
package org.mian.gitnex.activities;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.SponsorsAdapter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Author M M Arif
@ -22,12 +28,27 @@ public class SponsorsActivity extends AppCompatActivity {
setContentView(R.layout.activity_sponsors);
ImageView closeActivity = findViewById(R.id.close);
TextView liberaPaySponsorsThomas = findViewById(R.id.liberaPaySponsorsThomas);
liberaPaySponsorsThomas.setMovementMethod(LinkMovementMethod.getInstance());
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
Resources res = getResources();
CharSequence[] sponsorsInfo = res.getTextArray(R.array.sponsorsInfo);
List<CharSequence> sponsorsList = new ArrayList<>(Arrays.asList(sponsorsInfo));
RecyclerView mRecyclerView = findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
SponsorsAdapter adapter = new SponsorsAdapter(sponsorsList);
mRecyclerView.setAdapter(adapter);
}
private void initCloseListener() {

View File

@ -11,6 +11,7 @@ import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
@ -109,7 +110,7 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
private TextView issueTitle;
private TextView issueCreatedTime;
private TextView issueCommentsCount;
private ImageView issueType;
private RelativeLayout relativeLayoutFrame;
IssuesHolder(View itemView) {
@ -121,7 +122,7 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount);
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
issueType = itemView.findViewById(R.id.issueType);
relativeLayoutFrame = itemView.findViewById(R.id.relativeLayoutFrame);
issueTitle.setOnClickListener(new View.OnClickListener() {
@Override
@ -135,6 +136,7 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "issue");
context.startActivity(intent);
}
@ -151,6 +153,7 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "issue");
context.startActivity(intent);
}
@ -165,6 +168,13 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
/*if(issuesModel.getPull_request() != null) {
if (issuesModel.getPull_request().isMerged()) {
relativeLayoutFrame.setVisibility(View.GONE);
relativeLayoutFrame.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
}
}*/
if (!issuesModel.getUser().getFull_name().equals("")) {
issueAssigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueCreator) + issuesModel.getUser().getFull_name(), context));
} else {
@ -177,14 +187,6 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar);
}
if (issuesModel.getPull_request() == null) {
issueType.setImageResource(R.drawable.ic_issues);
issueType.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueTypeIssue), context));
} else {
issueType.setImageResource(R.drawable.ic_merge);
issueType.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueTypePullRequest), context));
}
String issueNumber_ = "<font color='" + context.getResources().getColor(R.color.lightGray) + "'>" + context.getResources().getString(R.string.hash) + issuesModel.getNumber() + "</font>";
issueTitle.setText(Html.fromHtml(issueNumber_ + " " + issuesModel.getTitle()));

View File

@ -0,0 +1,59 @@
package org.mian.gitnex.adapters;
import android.text.SpannableStringBuilder;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import java.util.List;
/**
* Author M M Arif
*/
public class CreditsAdapter extends RecyclerView.Adapter<CreditsAdapter.CreditsViewHolder> {
private List<CharSequence> creditsList;
static class CreditsViewHolder extends RecyclerView.ViewHolder {
private TextView creditText;
private CreditsViewHolder(View itemView) {
super(itemView);
creditText = itemView.findViewById(R.id.creditText);
}
}
public CreditsAdapter(List<CharSequence> creditsListMain) {
this.creditsList = creditsListMain;
}
@NonNull
@Override
public CreditsAdapter.CreditsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.credits, parent, false);
return new CreditsAdapter.CreditsViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull CreditsAdapter.CreditsViewHolder holder, int position) {
SpannableStringBuilder strBuilder = new SpannableStringBuilder(creditsList.get(position));
holder.creditText.setText((strBuilder));
holder.creditText.setMovementMethod(LinkMovementMethod.getInstance());
}
@Override
public int getItemCount() {
return creditsList.size();
}
}

View File

@ -0,0 +1,216 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.util.TinyDB;
import java.lang.reflect.Field;
import java.util.List;
/**
* Author M M Arif
*/
public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepositoriesAdapter.ReposSearchViewHolder> {
private List<UserRepositories> searchedReposList;
private Context mCtx;
public ExploreRepositoriesAdapter(List<UserRepositories> dataList, Context mCtx) {
this.mCtx = mCtx;
this.searchedReposList = dataList;
}
static class ReposSearchViewHolder extends RecyclerView.ViewHolder {
private ImageView image;
private TextView mTextView1;
private TextView mTextView2;
private TextView fullName;
private ImageView repoPrivatePublic;
private TextView repoStars;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private ReposSearchViewHolder(View itemView) {
super(itemView);
mTextView1 = itemView.findViewById(R.id.repoName);
mTextView2 = itemView.findViewById(R.id.repoDescription);
image = itemView.findViewById(R.id.imageAvatar);
fullName = itemView.findViewById(R.id.repoFullName);
repoPrivatePublic = itemView.findViewById(R.id.imageRepoType);
repoStars = itemView.findViewById(R.id.repoStars);
repoForks = itemView.findViewById(R.id.repoForks);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
TextView repoFullName = v.findViewById(R.id.repoFullName);
Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", repoFullName.getText().toString());
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putBoolean("resumeIssues", true);
context.startActivity(intent);
}
});
reposDropdownMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Context context = v.getContext();
Context context_ = new ContextThemeWrapper(context, R.style.popupMenuStyle);
PopupMenu popupMenu = new PopupMenu(context_, v);
popupMenu.inflate(R.menu.repo_dotted_list_menu);
Object menuHelper;
Class[] argTypes;
try {
Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup");
fMenuHelper.setAccessible(true);
menuHelper = fMenuHelper.get(popupMenu);
argTypes = new Class[] { boolean.class };
menuHelper.getClass().getDeclaredMethod("setForceShowIcon",
argTypes).invoke(menuHelper, true);
} catch (Exception e) {
popupMenu.show();
return;
}
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.repoStargazers:
Intent intent = new Intent(context, RepoStargazersActivity.class);
intent.putExtra("repoFullNameForStars", fullName.getText());
context.startActivity(intent);
break;
case R.id.repoWatchers:
Intent intentW = new Intent(context, RepoWatchersActivity.class);
intentW.putExtra("repoFullNameForWatchers", fullName.getText());
context.startActivity(intentW);
break;
case R.id.repoOpenInBrowser:
Intent intentOpenInBrowser = new Intent(context, OpenRepoInBrowserActivity.class);
intentOpenInBrowser.putExtra("repoFullNameBrowser", fullName.getText());
context.startActivity(intentOpenInBrowser);
break;
}
return false;
}
});
popupMenu.show();
}
});
}
}
@NonNull
@Override
public ExploreRepositoriesAdapter.ReposSearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.repos_list, parent, false);
return new ExploreRepositoriesAdapter.ReposSearchViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull final ExploreRepositoriesAdapter.ReposSearchViewHolder holder, int position) {
final UserRepositories currentItem = searchedReposList.get(position);
holder.mTextView2.setVisibility(View.GONE);
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
String firstCharacter = String.valueOf(currentItem.getName().charAt(0));
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.useFont(Typeface.DEFAULT)
.fontSize(18)
.toUpperCase()
.width(28)
.height(28)
.endConfig()
.buildRoundRect(firstCharacter, color, 3);
if (currentItem.getAvatar_url() != null) {
if (!currentItem.getAvatar_url().equals("")) {
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
} else {
holder.image.setImageDrawable(drawable);
}
}
else {
holder.image.setImageDrawable(drawable);
}
holder.mTextView1.setText(currentItem.getName());
if (!currentItem.getDescription().equals("")) {
holder.mTextView2.setVisibility(View.VISIBLE);
holder.mTextView2.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullname());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold);
}
else {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_public);
}
holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count());
holder.repoOpenIssuesCount.setText(currentItem.getOpen_issues_count());
}
@Override
public int getItemCount() {
return searchedReposList.size();
}
}

View File

@ -0,0 +1,212 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Files;
import java.util.ArrayList;
import java.util.List;
/**
* Author M M Arif
*/
public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHolder> implements Filterable {
private List<Files> filesList;
private Context mCtx;
private List<Files> filesListFull;
private FilesAdapterListener filesListener;
public interface FilesAdapterListener {
void onClickDir(String str);
void onClickFile(String str);
}
class FilesViewHolder extends RecyclerView.ViewHolder {
private ImageView fileTypeImage;
private TextView fileName;
private TextView fileType;
private FilesViewHolder(View itemView) {
super(itemView);
fileName = itemView.findViewById(R.id.fileName);
fileTypeImage = itemView.findViewById(R.id.fileImage);
fileType = itemView.findViewById(R.id.fileType);
//ImageView filesDropdownMenu = itemView.findViewById(R.id.filesDropdownMenu);
fileName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
if(fileType.getText().toString().equals("file")) {
filesListener.onClickFile(fileName.getText().toString());
}
else if(fileType.getText().toString().equals("dir")) {
filesListener.onClickDir(fileName.getText().toString());
}
else {
Toasty.info(context, context.getString(R.string.filesGenericError));
}
}
});
/*filesDropdownMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Context context = v.getContext();
Context context_ = new ContextThemeWrapper(context, R.style.popupMenuStyle);
PopupMenu popupMenu = new PopupMenu(context_, v);
popupMenu.inflate(R.menu.files_dotted_list_menu);
Object menuHelper;
Class[] argTypes;
try {
Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup");
fMenuHelper.setAccessible(true);
menuHelper = fMenuHelper.get(popupMenu);
argTypes = new Class[] { boolean.class };
menuHelper.getClass().getDeclaredMethod("setForceShowIcon",
argTypes).invoke(menuHelper, true);
} catch (Exception e) {
popupMenu.show();
return;
}
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.deleteFile:
Intent intent = new Intent(context, DeleteFileActivity.class);
intent.putExtra("repoFullNameForDeleteFile", fullName.getText());
context.startActivity(intent);
break;
case R.id.editFile:
Intent intentW = new Intent(context, EditFileActivity.class);
intentW.putExtra("repoFullNameForEditFile", fullName.getText());
context.startActivity(intentW);
break;
case R.id.openInBrowser:
Intent intentOpenInBrowser = new Intent(context, OpenFileInBrowserActivity.class);
intentOpenInBrowser.putExtra("fileFullNameBrowser", fullName.getText());
context.startActivity(intentOpenInBrowser);
break;
}
return false;
}
});
popupMenu.show();
}
});*/
}
}
public FilesAdapter(Context mCtx, List<Files> filesListMain, FilesAdapterListener filesListener) {
this.mCtx = mCtx;
this.filesList = filesListMain;
filesListFull = new ArrayList<>(filesList);
this.filesListener = filesListener;
}
@NonNull
@Override
public FilesAdapter.FilesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.files_list, parent, false);
return new FilesAdapter.FilesViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull FilesAdapter.FilesViewHolder holder, int position) {
Files currentItem = filesList.get(position);
holder.fileType.setText(currentItem.getType());
holder.fileName.setText(currentItem.getName());
if(currentItem.getType().equals("file")) {
holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_file_new));
}
else if(currentItem.getType().equals("dir")) {
holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_folder_24));
}
else {
holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_question_mark_24));
}
}
@Override
public int getItemCount() {
return filesList.size();
}
@Override
public Filter getFilter() {
return filesFilter;
}
private Filter filesFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Files> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(filesListFull);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (Files item : filesListFull) {
if (item.getName().toLowerCase().contains(filterPattern) || item.getPath().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filesList.clear();
filesList.addAll((List) results.values);
notifyDataSetChanged();
}
};
}

View File

@ -0,0 +1,138 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.models.FileDiffView;
import java.util.List;
/**
* Author M M Arif
*/
public class FilesDiffAdapter extends RecyclerView.Adapter<FilesDiffAdapter.FilesDiffViewHolder> {
private List<FileDiffView> dataList;
private Context ctx;
static class FilesDiffViewHolder extends RecyclerView.ViewHolder {
private TextView fileContents;
private TextView fileName;
private TextView fileInfo;
private ImageView fileImage;
private HorizontalScrollView fileContentsView;
private LinearLayout allLines;
private FilesDiffViewHolder(View itemView) {
super(itemView);
fileContents = itemView.findViewById(R.id.fileContents);
fileName = itemView.findViewById(R.id.fileName);
fileInfo = itemView.findViewById(R.id.fileInfo);
fileImage = itemView.findViewById(R.id.fileImage);
fileContentsView = itemView.findViewById(R.id.fileContentsView);
allLines = itemView.findViewById(R.id.allLinesLayout);
}
}
public FilesDiffAdapter(List<FileDiffView> dataListMain, Context ctx) {
this.dataList = dataListMain;
this.ctx = ctx;
}
@NonNull
@Override
public FilesDiffAdapter.FilesDiffViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.files_diffs_list, parent, false);
return new FilesDiffAdapter.FilesDiffViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull FilesDiffViewHolder holder, int position) {
FileDiffView data = dataList.get(position);
if(data.isFileType()) {
holder.fileName.setText(data.getFileName());
holder.fileInfo.setVisibility(View.GONE);
//byte[] imageData = Base64.decode(data.getFileContents(), Base64.DEFAULT);
//Drawable imageDrawable = new BitmapDrawable(ctx.getResources(), BitmapFactory.decodeByteArray(imageData, 0, imageData.length));
//holder.fileImage.setImageDrawable(imageDrawable);
holder.fileContentsView.setVisibility(View.GONE);
}
else {
String[] splitData = data.getFileContents().split("\\R");
for (String eachSplit : splitData) {
TextView textLine = new TextView(ctx);
textLine.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
if (eachSplit.startsWith("+")) {
textLine.setText(eachSplit);
holder.allLines.addView(textLine);
textLine.setTextColor(ctx.getResources().getColor(R.color.colorPrimary));
textLine.setPadding(5, 5, 5, 5);
textLine.setBackgroundColor(ctx.getResources().getColor(R.color.diffAddedColor));
}
else if (eachSplit.startsWith("-")) {
textLine.setText(eachSplit);
holder.allLines.addView(textLine);
textLine.setTextColor(ctx.getResources().getColor(R.color.colorPrimary));
textLine.setPadding(5, 5, 5, 5);
textLine.setBackgroundColor(ctx.getResources().getColor(R.color.diffRemovedColor));
}
else {
if(eachSplit.length() > 0) {
textLine.setText(eachSplit);
holder.allLines.addView(textLine);
textLine.setTextColor(ctx.getResources().getColor(R.color.colorPrimary));
textLine.setPadding(5, 5, 5, 5);
textLine.setBackgroundColor(ctx.getResources().getColor(R.color.white));
}
}
}
holder.fileName.setText(data.getFileName());
if(!data.getFileInfo().equals("")) {
holder.fileInfo.setText(ctx.getResources().getString(R.string.fileDiffInfoChanges, data.getFileInfo()));
}
else {
holder.fileInfo.setVisibility(View.GONE);
}
}
}
@Override
public int getItemCount() {
return dataList.size();
}
}

View File

@ -11,6 +11,7 @@ import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
@ -109,7 +110,7 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
private TextView issueTitle;
private TextView issueCreatedTime;
private TextView issueCommentsCount;
private ImageView issueType;
private RelativeLayout relativeLayoutFrame;
IssuesHolder(View itemView) {
@ -121,7 +122,7 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount);
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
issueType = itemView.findViewById(R.id.issueType);
relativeLayoutFrame = itemView.findViewById(R.id.relativeLayoutFrame);
issueTitle.setOnClickListener(new View.OnClickListener() {
@Override
@ -135,6 +136,7 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "issue");
context.startActivity(intent);
}
@ -151,6 +153,7 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "issue");
context.startActivity(intent);
}
@ -165,6 +168,13 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
/*if(issuesModel.getPull_request() != null) {
if (!issuesModel.getPull_request().isMerged()) {
relativeLayoutFrame.setVisibility(View.GONE);
relativeLayoutFrame.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
}
}*/
if (!issuesModel.getUser().getFull_name().equals("")) {
issueAssigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueCreator) + issuesModel.getUser().getFull_name(), context));
} else {
@ -177,14 +187,6 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar);
}
if (issuesModel.getPull_request() == null) {
issueType.setImageResource(R.drawable.ic_issues);
issueType.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueTypeIssue), context));
} else {
issueType.setImageResource(R.drawable.ic_merge);
issueType.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueTypePullRequest), context));
}
String issueNumber_ = "<font color='" + context.getResources().getColor(R.color.lightGray) + "'>" + context.getResources().getString(R.string.hash) + issuesModel.getNumber() + "</font>";
issueTitle.setText(Html.fromHtml(issueNumber_ + " " + issuesModel.getTitle()));

View File

@ -50,6 +50,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
private TextView repoStarsMy;
private TextView repoForksMy;
private TextView repoOpenIssuesCountMy;
private TextView repoType;
private MyReposViewHolder(View itemView) {
super(itemView);
@ -62,6 +63,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
repoForksMy = itemView.findViewById(R.id.repoForksMy);
repoOpenIssuesCountMy = itemView.findViewById(R.id.repoOpenIssuesCountMy);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
@ -74,6 +76,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("repoFullName", fullNameMy.getText().toString());
tinyDb.putString("repoType", repoType.getText().toString());
tinyDb.putBoolean("resumeIssues", true);
context.startActivity(intent);
@ -198,9 +201,11 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
holder.fullNameMy.setText(currentItem.getFullname());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublicMy.setImageResource(R.drawable.ic_lock_bold);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublicMy.setImageResource(R.drawable.ic_public);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStarsMy.setText(currentItem.getStars_count());
holder.repoForksMy.setText(currentItem.getForks_count());

View File

@ -0,0 +1,279 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.models.PullRequests;
import org.mian.gitnex.util.TinyDB;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* Author M M Arif
*/
public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {
private Context context;
private final int TYPE_LOAD = 0;
private List<PullRequests> prList;
private List<PullRequests> prListFull;
private PullRequestsAdapter.OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public PullRequestsAdapter(Context context, List<PullRequests> prListMain) {
this.context = context;
this.prList = prListMain;
prListFull = new ArrayList<>(prList);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD){
return new PullRequestsAdapter.PullRequestsHolder(inflater.inflate(R.layout.repo_pr_list, parent,false));
}
else {
return new PullRequestsAdapter.LoadHolder(inflater.inflate(R.layout.row_load,parent,false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount()-1 && isMoreDataAvailable && !isLoading && loadMoreListener!=null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((PullRequestsAdapter.PullRequestsHolder)holder).bindData(prList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(prList.get(position).getTitle() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return prList.size();
}
class PullRequestsHolder extends RecyclerView.ViewHolder {
private TextView prNumber;
private ImageView assigneeAvatar;
private TextView prTitle;
private TextView prCreatedTime;
private TextView prCommentsCount;
PullRequestsHolder(View itemView) {
super(itemView);
prNumber = itemView.findViewById(R.id.prNumber);
assigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
prTitle = itemView.findViewById(R.id.prTitle);
prCommentsCount = itemView.findViewById(R.id.prCommentsCount);
LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount);
prCreatedTime = itemView.findViewById(R.id.prCreatedTime);
prTitle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", prNumber.getText());
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", prNumber.getText().toString());
tinyDb.putString("issueType", "pr");
context.startActivity(intent);
}
});
frameCommentsCount.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", prNumber.getText());
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", prNumber.getText().toString());
tinyDb.putString("issueType", "pr");
context.startActivity(intent);
}
});
}
@SuppressLint("SetTextI18n")
void bindData(PullRequests prModel){
final TinyDB tinyDb = new TinyDB(context);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
if (!prModel.getUser().getFull_name().equals("")) {
assigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.prCreator) + prModel.getUser().getFull_name(), context));
} else {
assigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.prCreator) + prModel.getUser().getLogin(), context));
}
if (prModel.getUser().getAvatar_url() != null) {
Picasso.get().load(prModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar);
} else {
Picasso.get().load(prModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar);
}
String prNumber_ = "<font color='" + context.getResources().getColor(R.color.lightGray) + "'>" + context.getResources().getString(R.string.hash) + prModel.getNumber() + "</font>";
prTitle.setText(Html.fromHtml(prNumber_ + " " + prModel.getTitle()));
prNumber.setText(String.valueOf(prModel.getNumber()));
prCommentsCount.setText(String.valueOf(prModel.getComments()));
switch (timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(prModel.getCreated_at());
prCreatedTime.setText(createdTime);
prCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(prModel.getCreated_at()), context));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(prModel.getCreated_at());
prCreatedTime.setText(createdTime);
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(prModel.getCreated_at());
prCreatedTime.setText(createdTime);
break;
}
}
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(PullRequestsAdapter.OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
@Override
public Filter getFilter() {
return prFilter;
}
private Filter prFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<PullRequests> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(prList);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (PullRequests item : prList) {
if (item.getTitle().toLowerCase().contains(filterPattern) || item.getBody().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
prList.clear();
prList.addAll((List) results.values);
notifyDataSetChanged();
}
};
}

View File

@ -77,7 +77,7 @@ public class RepoStargazersAdapter extends BaseAdapter {
private void initData(RepoStargazersAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = stargazersList.get(position);
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(viewHolder.memberAvatar);
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.memberAvatar);
if(!currentItem.getFullname().equals("")) {
viewHolder.memberName.setText(currentItem.getFullname());

View File

@ -77,7 +77,7 @@ public class RepoWatchersAdapter extends BaseAdapter {
private void initData(RepoWatchersAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = watchersList.get(position);
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(viewHolder.memberAvatar);
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.memberAvatar);
if(!currentItem.getFullname().equals("")) {
viewHolder.memberName.setText(currentItem.getFullname());

View File

@ -50,6 +50,7 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
private TextView repoStars;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private ReposViewHolder(View itemView) {
@ -63,6 +64,7 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
repoForks = itemView.findViewById(R.id.repoForks);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
@ -70,12 +72,14 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
Context context = v.getContext();
TextView repoFullName = v.findViewById(R.id.repoFullName);
TextView repoType_ = v.findViewById(R.id.repoType);
Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", repoFullName.getText().toString());
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putString("repoType", repoType_.getText().toString());
tinyDb.putBoolean("resumeIssues", true);
context.startActivity(intent);
@ -200,9 +204,11 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
holder.fullName.setText(currentItem.getFullname());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_public);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count());

View File

@ -50,6 +50,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
private TextView repoStars;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private OrgReposViewHolder(View itemView) {
super(itemView);
@ -62,6 +63,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
repoForks = itemView.findViewById(R.id.repoForks);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
@ -74,6 +76,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("repoFullName", fullName.getText().toString());
tinyDb.putString("repoType", repoType.getText().toString());
tinyDb.putBoolean("resumeIssues", true);
context.startActivity(intent);
@ -199,9 +202,11 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
holder.fullName.setText(currentItem.getFullname());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_public);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count());

View File

@ -0,0 +1,59 @@
package org.mian.gitnex.adapters;
import android.text.SpannableStringBuilder;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import java.util.List;
/**
* Author M M Arif
*/
public class SponsorsAdapter extends RecyclerView.Adapter<SponsorsAdapter.SponsorsViewHolder> {
private List<CharSequence> sponsorsList;
static class SponsorsViewHolder extends RecyclerView.ViewHolder {
private TextView sponsorText;
private SponsorsViewHolder(View itemView) {
super(itemView);
sponsorText = itemView.findViewById(R.id.sponsorText);
}
}
public SponsorsAdapter(List<CharSequence> sponsorsListMain) {
this.sponsorsList = sponsorsListMain;
}
@NonNull
@Override
public SponsorsAdapter.SponsorsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.sponsors, parent, false);
return new SponsorsAdapter.SponsorsViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull SponsorsAdapter.SponsorsViewHolder holder, int position) {
SpannableStringBuilder strBuilder = new SpannableStringBuilder(sponsorsList.get(position));
holder.sponsorText.setText((strBuilder));
holder.sponsorText.setMovementMethod(LinkMovementMethod.getInstance());
}
@Override
public int getItemCount() {
return sponsorsList.size();
}
}

View File

@ -50,6 +50,7 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
private TextView repoStars;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private StarredReposViewHolder(View itemView) {
super(itemView);
@ -62,6 +63,7 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
repoForks = itemView.findViewById(R.id.repoForks);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
@ -74,6 +76,7 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("repoFullName", fullName.getText().toString());
tinyDb.putString("repoType", repoType.getText().toString());
tinyDb.putBoolean("resumeIssues", true);
context.startActivity(intent);
@ -199,9 +202,11 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
holder.fullName.setText(currentItem.getFullname());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_public);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count());

View File

@ -156,7 +156,7 @@ public class UserSearchAdapter extends RecyclerView.Adapter<UserSearchAdapter.Us
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
Call<Collaborators> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, mCtx)
.getApiInterface()
.checkRepoCollaborator(Authorization.returnAuthentication(mCtx, loginUid, instanceToken), repoOwner, repoName, currentItem.getUsername());
@ -191,7 +191,7 @@ public class UserSearchAdapter extends RecyclerView.Adapter<UserSearchAdapter.Us
@Override
public void onFailure(@NonNull Call<Collaborators> call, @NonNull Throwable t) {
Log.i("onFailure", t.getMessage());
Log.i("onFailure", t.toString());
}
});

View File

@ -1,6 +1,15 @@
package org.mian.gitnex.clients;
import android.content.Context;
import androidx.annotation.NonNull;
import org.mian.gitnex.util.AppUtil;
import java.io.File;
import java.io.IOException;
import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
@ -11,21 +20,40 @@ import retrofit2.converter.gson.GsonConverterFactory;
public class IssuesService {
public static <S> S createService(Class<S> serviceClass, String instanceURL) {
public static <S> S createService(Class<S> serviceClass, String instanceURL, Context ctx) {
final boolean connToInternet = AppUtil.haveNetworkConnection(ctx);
File httpCacheDirectory = new File(ctx.getCacheDir(), "responses");
int cacheSize = 50 * 1024 * 1024; // 50MB
Cache cache = new Cache(httpCacheDirectory, cacheSize);
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(instanceURL)
.addConverterFactory(GsonConverterFactory.create())
//.client(httpClient.build())
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cache(cache)
//.addInterceptor(logging)
.addInterceptor(new Interceptor() {
@NonNull
@Override public Response intercept(@NonNull Chain chain) throws IOException {
Request request = chain.request();
if (connToInternet) {
request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build();
} else {
request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 30).build();
}
return chain.proceed(request);
}
})
.build();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(instanceURL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
return retrofit.create(serviceClass);
}

View File

@ -0,0 +1,61 @@
package org.mian.gitnex.clients;
import android.content.Context;
import androidx.annotation.NonNull;
import org.mian.gitnex.util.AppUtil;
import java.io.File;
import java.io.IOException;
import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Author M M Arif
*/
public class PullRequestsService {
public static <S> S createService(Class<S> serviceClass, String instanceURL, Context ctx) {
final boolean connToInternet = AppUtil.haveNetworkConnection(ctx);
File httpCacheDirectory = new File(ctx.getCacheDir(), "responses");
int cacheSize = 50 * 1024 * 1024; // 50MB
Cache cache = new Cache(httpCacheDirectory, cacheSize);
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cache(cache)
//.addInterceptor(logging)
.addInterceptor(new Interceptor() {
@NonNull
@Override public Response intercept(@NonNull Chain chain) throws IOException {
Request request = chain.request();
if (connToInternet) {
request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build();
} else {
request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 30).build();
}
return chain.proceed(request);
}
})
.build();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(instanceURL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
return retrofit.create(serviceClass);
}
}

View File

@ -1,7 +1,16 @@
package org.mian.gitnex.clients;
import android.content.Context;
import androidx.annotation.NonNull;
import org.mian.gitnex.interfaces.ApiInterface;
import org.mian.gitnex.util.AppUtil;
import java.io.File;
import java.io.IOException;
import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
@ -15,26 +24,45 @@ public class RetrofitClient {
private Retrofit retrofit;
private RetrofitClient(String instanceUrl) {
private RetrofitClient(String instanceUrl, Context ctx) {
final boolean connToInternet = AppUtil.haveNetworkConnection(ctx);
int cacheSize = 50 * 1024 * 1024; // 50MB
File httpCacheDirectory = new File(ctx.getCacheDir(), "responses");
Cache cache = new Cache(httpCacheDirectory, cacheSize);
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging);
retrofit = new Retrofit.Builder()
.baseUrl(instanceUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
//.client(httpClient.build())
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cache(cache)
//.addInterceptor(logging)
.addInterceptor(new Interceptor() {
@NonNull
@Override public Response intercept(@NonNull Chain chain) throws IOException {
Request request = chain.request();
if (connToInternet) {
request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build();
} else {
request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 30).build();
}
return chain.proceed(request);
}
})
.build();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(instanceUrl)
.client(okHttpClient)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create());
retrofit = builder.build();
}
public static synchronized RetrofitClient getInstance(String instanceUrl) {
return new RetrofitClient(instanceUrl);
public static synchronized RetrofitClient getInstance(String instanceUrl, Context ctx) {
return new RetrofitClient(instanceUrl, ctx);
}
public ApiInterface getApiInterface() {

View File

@ -6,27 +6,17 @@ import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.CreditsActivity;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.activities.SponsorsActivity;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.Objects;
import retrofit2.Response;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
@ -34,36 +24,28 @@ import retrofit2.Callback;
public class AboutFragment extends Fragment {
private TextView viewTextGiteaVersion;
private ProgressBar mProgressBar;
private LinearLayout pageContent;
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_about, container, false);
((MainActivity) Objects.requireNonNull(getActivity())).setActionBarTitle(getResources().getString(R.string.pageTitleAbout));
TinyDB tinyDb = new TinyDB(getContext());
String instanceUrl = tinyDb.getString("instanceUrl");
final TextView appVerBuild;
final TextView donationLink;
final TextView donationLinkPatreon;
final TextView translateLink;
final TextView creditsButton;
final TextView sponsorsButton;
final TextView appWebsite;
final TextView appRepo;
pageContent = v.findViewById(R.id.aboutFrame);
pageContent.setVisibility(View.GONE);
mProgressBar = v.findViewById(R.id.progress_bar);
appVerBuild = v.findViewById(R.id.appVerBuild);
viewTextGiteaVersion = v.findViewById(R.id.giteaVersion);
TextView viewTextGiteaVersion = v.findViewById(R.id.giteaVersion);
creditsButton = v.findViewById(R.id.creditsButton);
donationLink = v.findViewById(R.id.donationLink);
donationLinkPatreon = v.findViewById(R.id.donationLinkPatreon);
translateLink = v.findViewById(R.id.translateLink);
sponsorsButton = v.findViewById(R.id.sponsorsButton);
appWebsite = v.findViewById(R.id.appWebsite);
appRepo = v.findViewById(R.id.appRepo);
@ -90,6 +72,16 @@ public class AboutFragment extends Fragment {
}
});
translateLink.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse(getResources().getString(R.string.crowdInLink)));
startActivity(intent);
}
});
appWebsite.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent();
@ -122,67 +114,10 @@ public class AboutFragment extends Fragment {
}
});
boolean connToInternet = AppUtil.haveNetworkConnection(getContext());
if(!connToInternet) {
mProgressBar.setVisibility(View.GONE);
pageContent.setVisibility(View.VISIBLE);
} else {
giteaVer(instanceUrl);
}
String commit = getResources().getString(R.string.commitPage) + tinyDb.getString("giteaVersion");
viewTextGiteaVersion.setText(commit);
return v;
}
private void giteaVer(String instanceUrl) {
TinyDB tinyDb = new TinyDB(getContext());
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
Call<GiteaVersion> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getGiteaVersion(Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
call.enqueue(new Callback<GiteaVersion>() {
@Override
public void onResponse(@NonNull Call<GiteaVersion> call, @NonNull Response<GiteaVersion> response) {
if (response.isSuccessful()) {
if (response.code() == 200) {
GiteaVersion version = response.body();
assert version != null;
String commit = getResources().getString(R.string.commitPage) + version.getVersion();
viewTextGiteaVersion.setText(commit);
mProgressBar.setVisibility(View.GONE);
pageContent.setVisibility(View.VISIBLE);
}
}
else {
String commit = getResources().getString(R.string.commitPage);
viewTextGiteaVersion.setText(commit);
mProgressBar.setVisibility(View.GONE);
pageContent.setVisibility(View.VISIBLE);
}
}
@Override
public void onFailure(@NonNull Call<GiteaVersion> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
}

View File

@ -96,7 +96,7 @@ public class BranchesFragment extends Fragment {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
BranchesViewModel.loadBranchesList(instanceUrl, instanceToken, repoOwner, repoName);
BranchesViewModel.loadBranchesList(instanceUrl, instanceToken, repoOwner, repoName, getContext());
}
}, 50);
}
@ -127,7 +127,7 @@ public class BranchesFragment extends Fragment {
BranchesViewModel branchesModel = new ViewModelProvider(this).get(BranchesViewModel.class);
branchesModel.getBranchesList(instanceUrl, instanceToken, owner, repo).observe(this, new Observer<List<Branches>>() {
branchesModel.getBranchesList(instanceUrl, instanceToken, owner, repo, getContext()).observe(getViewLifecycleOwner(), new Observer<List<Branches>>() {
@Override
public void onChanged(@Nullable List<Branches> branchesListMain) {
adapter = new BranchesAdapter(getContext(), branchesListMain);

View File

@ -28,7 +28,6 @@ import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@ -120,14 +119,11 @@ public class ClosedIssuesFragment extends Fragment {
}
});
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerViewClosed.getContext(),
DividerItemDecoration.VERTICAL);
recyclerViewClosed.setHasFixedSize(true);
recyclerViewClosed.addItemDecoration(dividerItemDecoration);
recyclerViewClosed.setLayoutManager(new LinearLayoutManager(context));
recyclerViewClosed.setAdapter(adapterClosed);
apiClosed = IssuesService.createService(ApiInterface.class, instanceUrl);
apiClosed = IssuesService.createService(ApiInterface.class, instanceUrl, getContext());
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, issueState);
return v;
@ -190,7 +186,7 @@ public class ClosedIssuesFragment extends Fragment {
@Override
public void onFailure(@NonNull Call<List<Issues>> call, @NonNull Throwable t) {
Log.e(TAG, t.getMessage());
Log.e(TAG, t.toString());
}
});
@ -245,7 +241,7 @@ public class ClosedIssuesFragment extends Fragment {
@Override
public void onFailure(@NonNull Call<List<Issues>> call, @NonNull Throwable t) {
Log.e(TAG, t.getMessage());
Log.e(TAG, t.toString());
}
@ -263,11 +259,11 @@ public class ClosedIssuesFragment extends Fragment {
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setQueryHint(getContext().getString(R.string.strFilter));
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {

View File

@ -100,7 +100,7 @@ public class CollaboratorsFragment extends Fragment {
CollaboratorsViewModel collaboratorsModel = new ViewModelProvider(this).get(CollaboratorsViewModel.class);
collaboratorsModel.getCollaboratorsList(instanceUrl, instanceToken, owner, repo).observe(this, new Observer<List<Collaborators>>() {
collaboratorsModel.getCollaboratorsList(instanceUrl, instanceToken, owner, repo, getContext()).observe(getViewLifecycleOwner(), new Observer<List<Collaborators>>() {
@Override
public void onChanged(@Nullable List<Collaborators> collaboratorsListMain) {
adapter = new CollaboratorsAdapter(getContext(), collaboratorsListMain);

View File

@ -0,0 +1,186 @@
package org.mian.gitnex.fragments;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.adapters.ExploreRepositoriesAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.ExploreRepositories;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
+ * Template Author M M Arif
+ * Author 6543
+ */
public class ExploreRepositoriesFragment extends Fragment {
private static String repoNameF = "param2";
private static String repoOwnerF = "param1";
private ProgressBar mProgressBar;
private RecyclerView mRecyclerView;
private TextView noData;
private TextView searchKeyword;
private Boolean repoTypeInclude = true;
private String sort = "updated";
private String order = "desc";
private int limit = 50;
private OnFragmentInteractionListener mListener;
public ExploreRepositoriesFragment() {
}
public static ExploreRepositoriesFragment newInstance(String param1, String param2) {
ExploreRepositoriesFragment fragment = new ExploreRepositoriesFragment();
Bundle args = new Bundle();
args.putString(repoOwnerF, param1);
args.putString(repoNameF, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
String repoName = getArguments().getString(repoNameF);
String repoOwner = getArguments().getString(repoOwnerF);
}
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext()));
final View v = inflater.inflate(R.layout.fragment_explore_repo, container, false);
//setHasOptionsMenu(true);
((MainActivity) Objects.requireNonNull(getActivity())).setActionBarTitle(getResources().getString(R.string.pageTitleExplore));
TinyDB tinyDb = new TinyDB(getContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
searchKeyword = v.findViewById(R.id.searchKeyword);
noData = v.findViewById(R.id.noData);
mProgressBar = v.findViewById(R.id.progress_bar);
mRecyclerView = v.findViewById(R.id.recyclerViewReposSearch);
searchKeyword.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEND) {
if(!searchKeyword.getText().toString().equals("")) {
mProgressBar.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.GONE);
loadSearchReposList(instanceUrl, instanceToken, loginUid, searchKeyword.getText().toString(), repoTypeInclude, sort, order, getContext(), limit);
}
}
return false;
}
});
return v;
}
private void loadSearchReposList(String instanceUrl, String instanceToken, String loginUid, String searchKeyword, Boolean repoTypeInclude, String sort, String order, final Context context, int limit) {
Call<ExploreRepositories> call = RetrofitClient
.getInstance(instanceUrl, getContext())
.getApiInterface()
.queryRepos(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), searchKeyword, repoTypeInclude, sort, order, limit);
call.enqueue(new Callback<ExploreRepositories>() {
@Override
public void onResponse(@NonNull Call<ExploreRepositories> call, @NonNull Response<ExploreRepositories> response) {
if (response.isSuccessful()) {
assert response.body() != null;
getReposList(response.body().getSearchedData(), context);
} else {
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<ExploreRepositories> call, @NonNull Throwable t) {
Log.i("onFailure", Objects.requireNonNull(t.getMessage()));
}
});
}
private void getReposList(List<UserRepositories> dataList, Context context) {
ExploreRepositoriesAdapter adapter = new ExploreRepositoriesAdapter(dataList, context);
mRecyclerView.setVisibility(View.VISIBLE);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noData.setVisibility(View.GONE);
mProgressBar.setVisibility(View.GONE);
}
else {
noData.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
}

View File

@ -0,0 +1,305 @@
package org.mian.gitnex.fragments;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.FileViewActivity;
import org.mian.gitnex.adapters.FilesAdapter;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.Files;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.FilesViewModel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import moe.feng.common.view.breadcrumbs.BreadcrumbsView;
import moe.feng.common.view.breadcrumbs.DefaultBreadcrumbsCallback;
import moe.feng.common.view.breadcrumbs.model.BreadcrumbItem;
/**
* Author M M Arif
*/
public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapterListener {
private ProgressBar mProgressBar;
private FilesAdapter adapter;
private RecyclerView mRecyclerView;
private TextView noDataFiles;
private LinearLayout filesFrame;
private TextView fileStructure;
private static String repoNameF = "param2";
private static String repoOwnerF = "param1";
private BreadcrumbsView mBreadcrumbsView;
private String repoName;
private String repoOwner;
private OnFragmentInteractionListener mListener;
public FilesFragment() {
}
public static FilesFragment newInstance(String param1, String param2) {
FilesFragment fragment = new FilesFragment();
Bundle args = new Bundle();
args.putString(repoOwnerF, param1);
args.putString(repoNameF, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
repoName = getArguments().getString(repoNameF);
repoOwner = getArguments().getString(repoOwnerF);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_files, container, false);
setHasOptionsMenu(true);
TinyDB tinyDb = new TinyDB(getContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
noDataFiles = v.findViewById(R.id.noDataFiles);
filesFrame = v.findViewById(R.id.filesFrame);
fileStructure = v.findViewById(R.id.fileStructure);
mRecyclerView = v.findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
mProgressBar = v.findViewById(R.id.progress_bar);
mBreadcrumbsView = v.findViewById(R.id.breadcrumbs_view);
mBreadcrumbsView.setItems(new ArrayList<>(Arrays.asList(
BreadcrumbItem.createSimpleItem(getResources().getString(R.string.filesBreadcrumbRoot))
)));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
return v;
}
@Override
public void onResume() {
super.onResume();
}
private static BreadcrumbItem createItem(String title) {
List<String> list = new ArrayList<>();
list.add(title);
return new BreadcrumbItem(list);
}
@Override
public void onClickDir(String dirName) {
TinyDB tinyDb = new TinyDB(getContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
StringBuilder breadcrumbBuilder = new StringBuilder();
breadcrumbBuilder.append(fileStructure.getText().toString()).append("/").append(dirName);
fileStructure.setText(breadcrumbBuilder);
String dirName_ = fileStructure.getText().toString();
dirName_ = dirName_.startsWith("/") ? dirName_.substring(1) : dirName_;
final String finalDirName_ = dirName_;
mBreadcrumbsView.addItem(createItem(dirName));
mBreadcrumbsView.setCallback(new DefaultBreadcrumbsCallback<BreadcrumbItem>() {
@Override
public void onNavigateBack(BreadcrumbItem item, int position) {
if(position == 0) {
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
fileStructure.setText("");
return;
}
String filterDir = fileStructure.getText().toString();
String result = filterDir.substring(0, filterDir.indexOf(item.getSelectedItem()));
fileStructure.setText(result + item.getSelectedItem());
fetchDataAsyncSub(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, finalDirName_);
}
@Override
public void onNavigateNewLocation(BreadcrumbItem newItem, int changedPosition) {
}
});
fetchDataAsyncSub(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, finalDirName_);
}
@Override
public void onClickFile(String fileName) {
Intent intent = new Intent(getContext(), FileViewActivity.class);
if(!fileStructure.getText().toString().equals("Root")) {
intent.putExtra("singleFileName", fileStructure.getText().toString()+"/"+fileName);
}
else {
intent.putExtra("singleFileName", fileName);
}
Objects.requireNonNull(getContext()).startActivity(intent);
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner, String repo) {
mRecyclerView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
FilesViewModel filesModel = new ViewModelProvider(this).get(FilesViewModel.class);
filesModel.getFilesList(instanceUrl, instanceToken, owner, repo, getContext()).observe(getViewLifecycleOwner(), new Observer<List<Files>>() {
@Override
public void onChanged(@Nullable List<Files> filesListMain) {
adapter = new FilesAdapter(getContext(), filesListMain, FilesFragment.this);
mBreadcrumbsView.removeItemAfter(1);
if(adapter.getItemCount() > 0) {
mRecyclerView.setVisibility(View.VISIBLE);
mRecyclerView.setAdapter(adapter);
filesFrame.setVisibility(View.VISIBLE);
noDataFiles.setVisibility(View.GONE);
}
else {
mRecyclerView.setVisibility(View.VISIBLE);
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
filesFrame.setVisibility(View.VISIBLE);
noDataFiles.setVisibility(View.VISIBLE);
}
filesFrame.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
});
}
private void fetchDataAsyncSub(String instanceUrl, String instanceToken, String owner, String repo, String filesDir) {
mRecyclerView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
FilesViewModel filesModel2 = new ViewModelProvider(this).get(FilesViewModel.class);
filesModel2.getFilesList2(instanceUrl, instanceToken, owner, repo, filesDir, getContext()).observe(this, new Observer<List<Files>>() {
@Override
public void onChanged(@Nullable List<Files> filesListMain2) {
adapter = new FilesAdapter(getContext(), filesListMain2, FilesFragment.this);
if(adapter.getItemCount() > 0) {
mRecyclerView.setVisibility(View.VISIBLE);
mRecyclerView.setAdapter(adapter);
filesFrame.setVisibility(View.VISIBLE);
noDataFiles.setVisibility(View.GONE);
}
else {
mRecyclerView.setVisibility(View.VISIBLE);
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
filesFrame.setVisibility(View.VISIBLE);
noDataFiles.setVisibility(View.VISIBLE);
}
filesFrame.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
});
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext()));
inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
//searchView.setQueryHint(getContext().getString(R.string.search));
/*if(!connToInternet) {
return;
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if(mRecyclerView.getAdapter() != null) {
adapter.getFilter().filter(newText);
}
return false;
}
});
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
}

View File

@ -5,7 +5,6 @@ import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@ -119,14 +118,11 @@ public class IssuesFragment extends Fragment {
}
});
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
DividerItemDecoration.VERTICAL);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.setAdapter(adapter);
api = IssuesService.createService(ApiInterface.class, instanceUrl);
api = IssuesService.createService(ApiInterface.class, instanceUrl, getContext());
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
return v;
@ -189,7 +185,7 @@ public class IssuesFragment extends Fragment {
@Override
public void onFailure(@NonNull Call<List<Issues>> call, @NonNull Throwable t) {
Log.e(TAG, t.getMessage());
Log.e(TAG, t.toString());
}
});
@ -244,7 +240,7 @@ public class IssuesFragment extends Fragment {
@Override
public void onFailure(@NonNull Call<List<Issues>> call, @NonNull Throwable t) {
Log.e(TAG, t.getMessage());
Log.e(TAG, t.toString());
}
@ -262,11 +258,11 @@ public class IssuesFragment extends Fragment {
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setQueryHint(getContext().getString(R.string.strFilter));
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {

View File

@ -94,7 +94,7 @@ public class LabelsFragment extends Fragment {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
LabelsViewModel.loadLabelsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
LabelsViewModel.loadLabelsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, getContext());
}
}, 200);
}
@ -119,7 +119,7 @@ public class LabelsFragment extends Fragment {
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getBoolean("labelsRefresh")) {
LabelsViewModel.loadLabelsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
LabelsViewModel.loadLabelsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, getContext());
tinyDb.putBoolean("labelsRefresh", false);
}
}
@ -144,7 +144,7 @@ public class LabelsFragment extends Fragment {
LabelsViewModel labelsModel = new ViewModelProvider(this).get(LabelsViewModel.class);
labelsModel.getLabelsList(instanceUrl, instanceToken, owner, repo).observe(this, new Observer<List<Labels>>() {
labelsModel.getLabelsList(instanceUrl, instanceToken, owner, repo, getContext()).observe(getViewLifecycleOwner(), new Observer<List<Labels>>() {
@Override
public void onChanged(@Nullable List<Labels> labelsListMain) {
adapter = new LabelsAdapter(getContext(), labelsListMain);

View File

@ -83,7 +83,7 @@ public class MembersByOrgFragment extends Fragment {
MembersByOrgViewModel membersModel= new ViewModelProvider(this).get(MembersByOrgViewModel.class);
membersModel.getMembersList(instanceUrl, instanceToken, owner).observe(this, new Observer<List<UserInfo>>() {
membersModel.getMembersList(instanceUrl, instanceToken, owner, getContext()).observe(getViewLifecycleOwner(), new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> membersListMain) {
adapter = new MembersByOrgAdapter(getContext(), membersListMain);
@ -112,7 +112,7 @@ public class MembersByOrgFragment extends Fragment {
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setQueryHint(getContext().getString(R.string.strFilter));
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
if(!connToInternet) {
return;

View File

@ -104,7 +104,7 @@ public class MilestonesFragment extends Fragment {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
MilestonesViewModel.loadMilestonesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, msState);
MilestonesViewModel.loadMilestonesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, msState, getContext());
}
}, 50);
}
@ -128,7 +128,7 @@ public class MilestonesFragment extends Fragment {
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getBoolean("milestoneCreated")) {
MilestonesViewModel.loadMilestonesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, msState);
MilestonesViewModel.loadMilestonesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, msState, getContext());
tinyDb.putBoolean("milestoneCreated", false);
}
}
@ -153,7 +153,7 @@ public class MilestonesFragment extends Fragment {
MilestonesViewModel msModel = new ViewModelProvider(this).get(MilestonesViewModel.class);
msModel.getMilestonesList(instanceUrl, instanceToken, owner, repo, msState).observe(this, new Observer<List<Milestones>>() {
msModel.getMilestonesList(instanceUrl, instanceToken, owner, repo, msState, getContext()).observe(getViewLifecycleOwner(), new Observer<List<Milestones>>() {
@Override
public void onChanged(@Nullable List<Milestones> msListMain) {
adapter = new MilestonesAdapter(getContext(), msListMain);
@ -183,11 +183,11 @@ public class MilestonesFragment extends Fragment {
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setQueryHint(getContext().getString(R.string.strFilter));
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override

View File

@ -89,6 +89,7 @@ public class MyRepositoriesFragment extends Fragment {
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final String userLogin = tinyDb.getString("userLogin");
final SwipeRefreshLayout swipeRefresh = v.findViewById(R.id.pullToRefresh);
@ -131,27 +132,20 @@ public class MyRepositoriesFragment extends Fragment {
}
});
if(connToInternet) {
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
MyRepositoriesViewModel.loadMyReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), userLogin, getContext());
}
}, 50);
}
});
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
MyRepositoriesViewModel.loadMyReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), loginUid);
}
}, 50);
}
});
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), loginUid);
}
else {
mProgressBar.setVisibility(View.GONE);
}
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), userLogin);
return v;
@ -164,16 +158,17 @@ public class MyRepositoriesFragment extends Fragment {
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final String userLogin = tinyDb.getString("userLogin");
MyRepositoriesViewModel.loadMyReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), loginUid);
MyRepositoriesViewModel.loadMyReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), userLogin, getContext());
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String username) {
private void fetchDataAsync(String instanceUrl, String instanceToken, String userLogin) {
MyRepositoriesViewModel myRepoModel = new ViewModelProvider(this).get(MyRepositoriesViewModel.class);
myRepoModel.getCurrentUserRepositories(instanceUrl, instanceToken, username).observe(this, new Observer<List<UserRepositories>>() {
myRepoModel.getCurrentUserRepositories(instanceUrl, instanceToken, userLogin, getContext()).observe(getViewLifecycleOwner(), new Observer<List<UserRepositories>>() {
@Override
public void onChanged(@Nullable List<UserRepositories> myReposListMain) {
adapter = new MyReposListAdapter(getContext(), myReposListMain);
@ -203,11 +198,11 @@ public class MyRepositoriesFragment extends Fragment {
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setQueryHint(getContext().getString(R.string.strFilter));
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override

View File

@ -88,7 +88,7 @@ public class OrganizationInfoFragment extends Fragment {
private void getOrgInfo(String instanceUrl, String token, final String owner) {
Call<Organization> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getContext())
.getApiInterface()
.getOrganization(token, owner);

View File

@ -101,25 +101,20 @@ public class OrganizationsFragment extends Fragment {
}
});
if(connToInternet) {
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
OrganizationListViewModel.loadOrgsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
}
}, 50);
}
});
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
OrganizationListViewModel.loadOrgsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}
}, 50);
}
});
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
}
else {
mProgressBar.setVisibility(View.GONE);
}
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
return v;
@ -134,7 +129,7 @@ public class OrganizationsFragment extends Fragment {
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getBoolean("orgCreated")) {
OrganizationListViewModel.loadOrgsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
OrganizationListViewModel.loadOrgsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
tinyDb.putBoolean("orgCreated", false);
}
}
@ -143,7 +138,7 @@ public class OrganizationsFragment extends Fragment {
OrganizationListViewModel orgModel = new ViewModelProvider(this).get(OrganizationListViewModel.class);
orgModel.getUserOrgs(instanceUrl, instanceToken).observe(this, new Observer<List<UserOrganizations>>() {
orgModel.getUserOrgs(instanceUrl, instanceToken, getContext()).observe(getViewLifecycleOwner(), new Observer<List<UserOrganizations>>() {
@Override
public void onChanged(@Nullable List<UserOrganizations> orgsListMain) {
adapter = new OrganizationsListAdapter(getContext(), orgsListMain);
@ -173,11 +168,11 @@ public class OrganizationsFragment extends Fragment {
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setQueryHint(getContext().getString(R.string.strFilter));
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override

View File

@ -95,7 +95,7 @@ public class ProfileEmailsFragment extends Fragment {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
ProfileEmailsViewModel.loadEmailsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
ProfileEmailsViewModel.loadEmailsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}
}, 200);
}
@ -111,7 +111,7 @@ public class ProfileEmailsFragment extends Fragment {
ProfileEmailsViewModel profileEmailModel = new ViewModelProvider(this).get(ProfileEmailsViewModel.class);
profileEmailModel.getEmailsList(instanceUrl, instanceToken).observe(this, new Observer<List<Emails>>() {
profileEmailModel.getEmailsList(instanceUrl, instanceToken, getContext()).observe(getViewLifecycleOwner(), new Observer<List<Emails>>() {
@Override
public void onChanged(@Nullable List<Emails> emailsListMain) {
adapter = new ProfileEmailsAdapter(getContext(), emailsListMain);

View File

@ -95,7 +95,7 @@ public class ProfileFollowersFragment extends Fragment {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
ProfileFollowersViewModel.loadFollowersList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
ProfileFollowersViewModel.loadFollowersList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}
}, 200);
}
@ -110,7 +110,7 @@ public class ProfileFollowersFragment extends Fragment {
ProfileFollowersViewModel pfModel = new ViewModelProvider(this).get(ProfileFollowersViewModel.class);
pfModel.getFollowersList(instanceUrl, instanceToken).observe(this, new Observer<List<UserInfo>>() {
pfModel.getFollowersList(instanceUrl, instanceToken, getContext()).observe(getViewLifecycleOwner(), new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> pfListMain) {
adapter = new ProfileFollowersAdapter(getContext(), pfListMain);

View File

@ -95,7 +95,7 @@ public class ProfileFollowingFragment extends Fragment {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
ProfileFollowingViewModel.loadFollowingList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
ProfileFollowingViewModel.loadFollowingList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}
}, 200);
}
@ -110,7 +110,7 @@ public class ProfileFollowingFragment extends Fragment {
ProfileFollowingViewModel pfModel = new ViewModelProvider(this).get(ProfileFollowingViewModel.class);
pfModel.getFollowingList(instanceUrl, instanceToken).observe(this, new Observer<List<UserInfo>>() {
pfModel.getFollowingList(instanceUrl, instanceToken, getContext()).observe(getViewLifecycleOwner(), new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> pfListMain) {
adapter = new ProfileFollowingAdapter(getContext(), pfListMain);

View File

@ -0,0 +1,293 @@
package org.mian.gitnex.fragments;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.PullRequestsAdapter;
import org.mian.gitnex.clients.PullRequestsService;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.interfaces.ApiInterface;
import org.mian.gitnex.models.PullRequests;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class PullRequestsFragment extends Fragment {
private ProgressBar mProgressBar;
private RecyclerView recyclerView;
private List<PullRequests> prList;
private PullRequestsAdapter adapter;
private ApiInterface apiPR;
private String TAG = "PullRequestsListFragment - ";
private Context context;
private int pageSize = 1;
private TextView noData;
private String prState = "open";
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.fragment_pull_requests, container, false);
setHasOptionsMenu(true);
TinyDB tinyDb = new TinyDB(getContext());
String repoFullName = tinyDb.getString("repoFullName");
//Log.i("repoFullName", tinyDb.getString("repoFullName"));
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final SwipeRefreshLayout swipeRefresh = v.findViewById(R.id.pullToRefresh);
context = getContext();
recyclerView = v.findViewById(R.id.recyclerView);
prList = new ArrayList<>();
mProgressBar = v.findViewById(R.id.progress_bar);
noData = v.findViewById(R.id.noData);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
loadInitial(instanceToken, repoOwner, repoName, pageSize, prState);
adapter.notifyDataChanged();
}
}, 200);
}
});
adapter = new PullRequestsAdapter(getContext(), prList);
adapter.setLoadMoreListener(new PullRequestsAdapter.OnLoadMoreListener() {
@Override
public void onLoadMore() {
recyclerView.post(new Runnable() {
@Override
public void run() {
if(prList.size() == 10 || pageSize == 10) {
int page = (prList.size() + 10) / 10;
loadMore(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, page, prState);
}
/*else {
Toasty.info(context, getString(R.string.noMoreData));
}*/
}
});
}
});
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
DividerItemDecoration.VERTICAL);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.setAdapter(adapter);
apiPR = PullRequestsService.createService(ApiInterface.class, instanceUrl, getContext());
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, pageSize, prState);
return v;
}
@Override
public void onResume() {
super.onResume();
TinyDB tinyDb = new TinyDB(getContext());
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getBoolean("resumePullRequests")) {
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, pageSize, prState);
tinyDb.putBoolean("resumePullRequests", false);
}
}
private void loadInitial(String token, String repoOwner, String repoName, int page, String prState) {
Call<List<PullRequests>> call = apiPR.getPullRequests(token, repoOwner, repoName, page, prState);
call.enqueue(new Callback<List<PullRequests>>() {
@Override
public void onResponse(@NonNull Call<List<PullRequests>> call, @NonNull Response<List<PullRequests>> response) {
if(response.isSuccessful()) {
assert response.body() != null;
if(response.body().size() > 0) {
prList.clear();
prList.addAll(response.body());
adapter.notifyDataChanged();
noData.setVisibility(View.GONE);
}
else {
prList.clear();
adapter.notifyDataChanged();
noData.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
}
else {
Log.i(TAG, String.valueOf(response.code()));
}
Log.i("http", String.valueOf(response.code()));
}
@Override
public void onFailure(@NonNull Call<List<PullRequests>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
private void loadMore(String token, String repoOwner, String repoName, int page, String prState){
//add loading progress view
prList.add(new PullRequests("load"));
adapter.notifyItemInserted((prList.size() - 1));
Call<List<PullRequests>> call = apiPR.getPullRequests(token, repoOwner, repoName, page, prState);
call.enqueue(new Callback<List<PullRequests>>() {
@Override
public void onResponse(@NonNull Call<List<PullRequests>> call, @NonNull Response<List<PullRequests>> response) {
if(response.isSuccessful()){
//remove loading view
prList.remove(prList.size()-1);
List<PullRequests> result = response.body();
assert result != null;
if(result.size() > 0) {
pageSize = result.size();
prList.addAll(result);
}
else {
Toasty.info(context, getString(R.string.noMoreData));
adapter.setMoreDataAvailable(false);
}
adapter.notifyDataChanged();
}
else {
Log.e(TAG, String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<PullRequests>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext()));
inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
/*if(!connToInternet) {
return;
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
}
}

View File

@ -95,7 +95,7 @@ public class ReleasesFragment extends Fragment {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
ReleasesViewModel.loadReleasesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
ReleasesViewModel.loadReleasesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, getContext());
}
}, 50);
}
@ -117,7 +117,7 @@ public class ReleasesFragment extends Fragment {
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getBoolean("updateReleases")) {
ReleasesViewModel.loadReleasesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
ReleasesViewModel.loadReleasesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, getContext());
tinyDb.putBoolean("updateReleases", false);
}
@ -143,7 +143,7 @@ public class ReleasesFragment extends Fragment {
ReleasesViewModel releasesModel = new ViewModelProvider(this).get(ReleasesViewModel.class);
releasesModel.getReleasesList(instanceUrl, instanceToken, owner, repo).observe(this, new Observer<List<Releases>>() {
releasesModel.getReleasesList(instanceUrl, instanceToken, owner, repo, getContext()).observe(getViewLifecycleOwner(), new Observer<List<Releases>>() {
@Override
public void onChanged(@Nullable List<Releases> releasesListMain) {
adapter = new ReleasesAdapter(getContext(), releasesListMain);

View File

@ -8,6 +8,7 @@ import android.view.ViewGroup;
import android.widget.TextView;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.RepositoryActions;
import org.mian.gitnex.util.TinyDB;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -34,6 +35,10 @@ public class RepoBottomSheetFragment extends BottomSheetDialogFragment {
TextView createRelease = v.findViewById(R.id.createRelease);
TextView openWebRepo = v.findViewById(R.id.openWebRepo);
TextView newFile = v.findViewById(R.id.newFile);
TextView starRepository = v.findViewById(R.id.starRepository);
TextView unStarRepository = v.findViewById(R.id.unStarRepository);
TextView watchRepository = v.findViewById(R.id.watchRepository);
TextView unWatchRepository = v.findViewById(R.id.unWatchRepository);
createLabel.setOnClickListener(new View.OnClickListener() {
@Override
@ -97,6 +102,72 @@ public class RepoBottomSheetFragment extends BottomSheetDialogFragment {
}
});
if(tinyDb.getInt("repositoryStarStatus") == 204) { // star a repo
starRepository.setVisibility(View.GONE);
unStarRepository.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RepositoryActions.unStarRepository(getContext());
tinyDb.putInt("repositoryStarStatus", 404);
dismiss();
}
});
}
else if(tinyDb.getInt("repositoryStarStatus") == 404) {
unStarRepository.setVisibility(View.GONE);
starRepository.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RepositoryActions.starRepository(getContext());
tinyDb.putInt("repositoryStarStatus", 204);
dismiss();
}
});
}
if(tinyDb.getBoolean("repositoryWatchStatus")) { // watch a repo
watchRepository.setVisibility(View.GONE);
unWatchRepository.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RepositoryActions.unWatchRepository(getContext());
tinyDb.putBoolean("repositoryWatchStatus", false);
dismiss();
}
});
}
else {
unWatchRepository.setVisibility(View.GONE);
watchRepository.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RepositoryActions.watchRepository(getContext());
tinyDb.putBoolean("repositoryWatchStatus", true);
dismiss();
}
});
}
return v;
}

View File

@ -218,7 +218,7 @@ public class RepoInfoFragment extends Fragment {
final TinyDB tinyDb = new TinyDB(getContext());
Call<UserRepositories> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getContext())
.getApiInterface()
.getUserRepository(token, owner, repo);
@ -303,7 +303,7 @@ public class RepoInfoFragment extends Fragment {
final TinyDB tinyDb = new TinyDB(getContext());
Call<String> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getContext())
.getApiInterface()
.getFileContents(token, owner, repo, filename);

View File

@ -97,7 +97,7 @@ public class RepositoriesByOrgFragment extends Fragment {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
RepositoriesByOrgViewModel.loadOrgRepos(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName);
RepositoriesByOrgViewModel.loadOrgRepos(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName, getContext());
}
}, 200);
}
@ -117,7 +117,7 @@ public class RepositoriesByOrgFragment extends Fragment {
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
RepositoriesByOrgViewModel.loadOrgRepos(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName);
RepositoriesByOrgViewModel.loadOrgRepos(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName, getContext());
}
@ -125,7 +125,7 @@ public class RepositoriesByOrgFragment extends Fragment {
RepositoriesByOrgViewModel orgRepoModel = new ViewModelProvider(this).get(RepositoriesByOrgViewModel.class);
orgRepoModel.getRepositoriesByOrg(instanceUrl, instanceToken, owner).observe(this, new Observer<List<UserRepositories>>() {
orgRepoModel.getRepositoriesByOrg(instanceUrl, instanceToken, owner, getContext()).observe(getViewLifecycleOwner(), new Observer<List<UserRepositories>>() {
@Override
public void onChanged(@Nullable List<UserRepositories> orgReposListMain) {
adapter = new RepositoriesByOrgAdapter(getContext(), orgReposListMain);
@ -155,7 +155,7 @@ public class RepositoriesByOrgFragment extends Fragment {
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setQueryHint(getContext().getString(R.string.strFilter));
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
if(!connToInternet) {
return;

View File

@ -102,27 +102,20 @@ public class RepositoriesFragment extends Fragment {
}
});
if(connToInternet) {
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
RepositoriesListViewModel.loadReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}
}, 50);
}
});
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
RepositoriesListViewModel.loadReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
}
}, 50);
}
});
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
}
else {
mProgressBar.setVisibility(View.GONE);
}
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
return v;
@ -137,7 +130,7 @@ public class RepositoriesFragment extends Fragment {
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getBoolean("repoCreated")) {
RepositoriesListViewModel.loadReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
RepositoriesListViewModel.loadReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
tinyDb.putBoolean("repoCreated", false);
}
}
@ -146,7 +139,7 @@ public class RepositoriesFragment extends Fragment {
RepositoriesListViewModel repoModel = new ViewModelProvider(this).get(RepositoriesListViewModel.class);
repoModel.getUserRepositories(instanceUrl, instanceToken).observe(this, new Observer<List<UserRepositories>>() {
repoModel.getUserRepositories(instanceUrl, instanceToken, getContext()).observe(getViewLifecycleOwner(), new Observer<List<UserRepositories>>() {
@Override
public void onChanged(@Nullable List<UserRepositories> reposListMain) {
adapter = new ReposListAdapter(getContext(), reposListMain);
@ -176,11 +169,11 @@ public class RepositoriesFragment extends Fragment {
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setQueryHint(getContext().getString(R.string.strFilter));
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override

View File

@ -30,7 +30,7 @@ public class SettingsFragment extends Fragment {
private Context ctx = null;
private static String[] langList = {"English", "French", "German", "Russian"};
private static String[] langList = {"Arabic", "Chinese", "English", "Finnish", "French", "German", "Italian", "Persian", "Portuguese/Brazilian", "Russian", "Serbian", "Turkish", "Ukrainian"};
private static int langSelectedChoice = 0;
private static String[] timeList = {"Pretty", "Normal"};
@ -68,7 +68,7 @@ public class SettingsFragment extends Fragment {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse(getResources().getString(R.string.appRepoContributingLink)));
intent.setData(Uri.parse(getResources().getString(R.string.crowdInLink)));
startActivity(intent);
}
});
@ -244,15 +244,42 @@ public class SettingsFragment extends Fragment {
tinyDb.putInt("langId", i);
switch (langList[i]) {
case "Arabic":
tinyDb.putString("locale", "ar");
break;
case "Chinese":
tinyDb.putString("locale", "zh");
break;
case "Finnish":
tinyDb.putString("locale", "fi");
break;
case "French":
tinyDb.putString("locale", "fr");
break;
case "German":
tinyDb.putString("locale", "de");
break;
case "Italian":
tinyDb.putString("locale", "it");
break;
case "Persian":
tinyDb.putString("locale", "fa");
break;
case "Portuguese/Brazilian":
tinyDb.putString("locale", "pt");
break;
case "Russian":
tinyDb.putString("locale", "ru");
break;
case "Serbian":
tinyDb.putString("locale", "sr");
break;
case "Turkish":
tinyDb.putString("locale", "tr");
break;
case "Ukrainian":
tinyDb.putString("locale", "uk");
break;
default:
tinyDb.putString("locale", "en");
break;

View File

@ -12,6 +12,8 @@ import org.mian.gitnex.actions.IssueActions;
import org.mian.gitnex.activities.AddRemoveAssigneesActivity;
import org.mian.gitnex.activities.AddRemoveLabelsActivity;
import org.mian.gitnex.activities.EditIssueActivity;
import org.mian.gitnex.activities.FileDiffActivity;
import org.mian.gitnex.activities.MergePullRequestActivity;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
@ -19,6 +21,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.content.ClipboardManager;
import android.content.ClipData;
import java.util.Objects;
/**
* Author M M Arif
@ -41,6 +44,8 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
TextView reOpenIssue = v.findViewById(R.id.reOpenIssue);
TextView addRemoveAssignees = v.findViewById(R.id.addRemoveAssignees);
TextView copyIssueUrl = v.findViewById(R.id.copyIssueUrl);
TextView openFilesDiff = v.findViewById(R.id.openFilesDiff);
TextView mergePullRequest = v.findViewById(R.id.mergePullRequest);
replyToIssue.setOnClickListener(new View.OnClickListener() {
@Override
@ -52,6 +57,52 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
}
});
if(tinyDB.getString("issueType").equals("pr")) {
editIssue.setText(R.string.editPrText);
copyIssueUrl.setText(R.string.copyPrUrlText);
if(tinyDB.getBoolean("prMerged")) {
mergePullRequest.setVisibility(View.GONE);
}
else {
mergePullRequest.setVisibility(View.VISIBLE);
}
if(tinyDB.getString("repoType").equals("public")) {
openFilesDiff.setVisibility(View.VISIBLE);
}
else {
openFilesDiff.setVisibility(View.GONE);
}
}
else {
mergePullRequest.setVisibility(View.GONE);
}
mergePullRequest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getContext(), MergePullRequestActivity.class));
dismiss();
}
});
openFilesDiff.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getContext(), FileDiffActivity.class));
dismiss();
}
});
editIssue.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -89,7 +140,7 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
// get url of repo
String repoFullName = tinyDB.getString("repoFullName");
String instanceUrlWithProtocol = "https://" + tinyDB.getString("instanceUrlRaw");
if(!tinyDB.getString("instanceUrlWithProtocol").isEmpty()) {
if (!tinyDB.getString("instanceUrlWithProtocol").isEmpty()) {
instanceUrlWithProtocol = tinyDB.getString("instanceUrlWithProtocol");
}
@ -97,8 +148,9 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
String issueUrl = instanceUrlWithProtocol + "/" + repoFullName + "/issues/" + tinyDB.getString("issueNumber");
// copy to clipboard
ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(android.content.Context.CLIPBOARD_SERVICE);
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(getContext()).getSystemService(android.content.Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("issueUrl", issueUrl);
assert clipboard != null;
clipboard.setPrimaryClip(clip);
dismiss();
@ -108,35 +160,44 @@ public class SingleIssueBottomSheetFragment extends BottomSheetDialogFragment {
}
});
if(tinyDB.getString("issueState").equals("open")) { // close issue
if(tinyDB.getString("issueType").equals("issue")) {
reOpenIssue.setVisibility(View.GONE);
if (tinyDB.getString("issueState").equals("open")) { // close issue
closeIssue.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
reOpenIssue.setVisibility(View.GONE);
IssueActions.closeReopenIssue(getContext(), Integer.valueOf(tinyDB.getString("issueNumber")), "closed");
dismiss();
closeIssue.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
IssueActions.closeReopenIssue(getContext(), Integer.valueOf(tinyDB.getString("issueNumber")), "closed");
dismiss();
}
});
} else if (tinyDB.getString("issueState").equals("closed")) {
closeIssue.setVisibility(View.GONE);
reOpenIssue.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
IssueActions.closeReopenIssue(getContext(), Integer.valueOf(tinyDB.getString("issueNumber")), "open");
dismiss();
}
});
}
}
else if(tinyDB.getString("issueState").equals("closed")) {
else {
reOpenIssue.setVisibility(View.GONE);
closeIssue.setVisibility(View.GONE);
reOpenIssue.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
IssueActions.closeReopenIssue(getContext(), Integer.valueOf(tinyDB.getString("issueNumber")), "open");
dismiss();
}
});
}
return v;

View File

@ -127,27 +127,20 @@ public class StarredRepositoriesFragment extends Fragment {
}
});
if(connToInternet) {
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
StarredRepositoriesViewModel.loadStarredReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}
}, 50);
}
});
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
StarredRepositoriesViewModel.loadStarredReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
}
}, 50);
}
});
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
}
else {
mProgressBar.setVisibility(View.GONE);
}
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
return v;
}
@ -160,7 +153,7 @@ public class StarredRepositoriesFragment extends Fragment {
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
StarredRepositoriesViewModel.loadStarredReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));
StarredRepositoriesViewModel.loadStarredReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}
@ -168,7 +161,7 @@ public class StarredRepositoriesFragment extends Fragment {
StarredRepositoriesViewModel starredRepoModel = new ViewModelProvider(this).get(StarredRepositoriesViewModel.class);
starredRepoModel.getUserStarredRepositories(instanceUrl, instanceToken).observe(this, new Observer<List<UserRepositories>>() {
starredRepoModel.getUserStarredRepositories(instanceUrl, instanceToken, getContext()).observe(getViewLifecycleOwner(), new Observer<List<UserRepositories>>() {
@Override
public void onChanged(@Nullable List<UserRepositories> starredReposListMain) {
adapter = new StarredReposListAdapter(getContext(), starredReposListMain);
@ -198,11 +191,11 @@ public class StarredRepositoriesFragment extends Fragment {
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setQueryHint(getContext().getString(R.string.strFilter));
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override

View File

@ -97,7 +97,7 @@ public class TeamsByOrgFragment extends Fragment {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
TeamsByOrgViewModel.loadTeamsByOrgList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName);
TeamsByOrgViewModel.loadTeamsByOrgList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName, getContext());
}
}, 200);
}
@ -117,7 +117,7 @@ public class TeamsByOrgFragment extends Fragment {
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getBoolean("resumeTeams")) {
TeamsByOrgViewModel.loadTeamsByOrgList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName);
TeamsByOrgViewModel.loadTeamsByOrgList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName, getContext());
tinyDb.putBoolean("resumeTeams", false);
}
}
@ -126,7 +126,7 @@ public class TeamsByOrgFragment extends Fragment {
TeamsByOrgViewModel teamModel = new ViewModelProvider(this).get(TeamsByOrgViewModel.class);
teamModel.getTeamsByOrg(instanceUrl, instanceToken, owner).observe(this, new Observer<List<Teams>>() {
teamModel.getTeamsByOrg(instanceUrl, instanceToken, owner, getContext()).observe(getViewLifecycleOwner(), new Observer<List<Teams>>() {
@Override
public void onChanged(@Nullable List<Teams> orgTeamsListMain) {
adapter = new TeamsByOrgAdapter(getContext(), orgTeamsListMain);
@ -156,11 +156,11 @@ public class TeamsByOrgFragment extends Fragment {
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setQueryHint(getContext().getString(R.string.strFilter));
//searchView.setQueryHint(getContext().getString(R.string.strFilter));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override

View File

@ -0,0 +1,135 @@
package org.mian.gitnex.helpers;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Author 6543
*/
public enum VersionCheck {
UNKNOWN,
SUPPORTED_LATEST,
SUPPORTED_OLD,
DEVELOPMENT,
UNSUPPORTED_OLD,
UNSUPPORTED_NEW;
public static VersionCheck check(String min, String last, String value) {
final Pattern pattern_stable_release = Pattern.compile("^(\\d)\\.(\\d+)\\.(\\d+)$");
final Pattern pattern_dev_release = Pattern.compile("^(\\d).(\\d+).(\\d+)(\\D)(.+)");
Matcher match;
if (!pattern_stable_release.matcher(min).find() || !pattern_stable_release.matcher(last).find()) {
throw new IllegalArgumentException("VersionCheck: wrong format for min or last version given");
}
match = pattern_stable_release.matcher(value);
if (match.find()) {
switch (correlate(min, last, match.group())){
case 0:
return UNSUPPORTED_OLD;
case 1:
return SUPPORTED_OLD;
case 2:
return SUPPORTED_LATEST;
default:
return UNSUPPORTED_NEW;
}
}
match = pattern_dev_release.matcher(value);
if (match.find()) {
match = Pattern.compile("^(\\d)\\.(\\d+)\\.(\\d+)").matcher(value);
match.find();
if (correlate(min, last, match.group())>0) {
return DEVELOPMENT;
}
else {
return UNSUPPORTED_OLD;
}
}
return UNKNOWN;
}
//helper
// 0 to less
// 1 in range
// 2 at the top
// 3 above
private static int correlate(String min, String last, String value){
int min_check = compareVersion(value,min);
int max_check = compareVersion(value,last);
int range_check = compareVersion(min,last);
switch (range_check) {
case 2:
throw new IllegalArgumentException("Minimum Version higher than Last Version");
case 1: //min == last
switch (min_check) {
case 0:
return 0;
case 1:
return 2;
default:
return 3;
}
default:
if (max_check >1) return 3;
if (max_check == 1) return 2;
if (min_check < 1) return 0;
return 1;
}
}
/**
* @description compare doted formatted Versions
* @param A doted formatted Versions
* @param B doted formatted Versions
* @return 0|1|2
* 0 = less
* 1 = same
* 2 = more
*/
public static int compareVersion(String A, String B) {
//throw new IllegalArgumentException
if((!A.matches("[0-9]+(\\.[0-9]+)*")) || (!B.matches("[0-9]+(\\.[0-9]+)*"))) throw new IllegalArgumentException("Invalid version format");
if (A.contains(".") || B.contains(".")) {
// example 2 vs 1.3
if (!(A.contains(".") && B.contains("."))) {
if (A.contains(".")) {
return compareVersion(A,B + ".0");
}
if (B.contains(".")) {
return compareVersion(A + ".0",B);
}
}
//normal compare
int a = Integer.parseInt(A.substring(0,A.indexOf(".")));
int b = Integer.parseInt(B.substring(0,B.indexOf(".")));
if (a < b) return 0;
if (a == b) return compareVersion(A.substring(A.indexOf(".")+1),B.substring(B.indexOf(".")+1));
return 2; //if (a > b)
}
else {
int a = Integer.parseInt(A);
int b = Integer.parseInt(B);
if (a < b) return 0;
if (a == b) return 1;
return 2; //if (a > b)
}
}
}

View File

@ -3,7 +3,11 @@ package org.mian.gitnex.interfaces;
import com.google.gson.JsonElement;
import org.mian.gitnex.models.AddEmail;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.ExploreRepositories;
import org.mian.gitnex.models.Files;
import org.mian.gitnex.models.MergePullRequest;
import org.mian.gitnex.models.NewFile;
import org.mian.gitnex.models.PullRequests;
import org.mian.gitnex.models.UpdateIssueAssignee;
import org.mian.gitnex.models.UpdateIssueState;
import org.mian.gitnex.models.Collaborators;
@ -26,7 +30,9 @@ import org.mian.gitnex.models.UserOrganizations;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.UserSearch;
import org.mian.gitnex.models.UserTokens;
import org.mian.gitnex.models.WatchRepository;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
@ -45,7 +51,7 @@ import retrofit2.http.Query;
public interface ApiInterface {
@GET("version") // gitea version API
Call<GiteaVersion> getGiteaVersion(@Header("Authorization") String token);
Call<GiteaVersion> getGiteaVersion();
@GET("user") // username, full name, email
Call<UserInfo> getUserInfo(@Header("Authorization") String token);
@ -212,6 +218,45 @@ public interface ApiInterface {
@GET("repos/{owner}/{repo}/subscribers") // get all repo watchers
Call<List<UserInfo>> getRepoWatchers(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@GET("repos/search") // get all the repos which match the query string
Call<ExploreRepositories> queryRepos(@Header("Authorization") String token, @Query("q") String searchKeyword, @Query("private") Boolean repoTypeInclude, @Query("sort") String sort, @Query("order") String order, @Query("limit") int limit);
@POST("repos/{owner}/{repo}/contents/{file}") // create new file
Call<JsonElement> createNewFile(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("file") String fileName, @Body NewFile jsonStr);
}
@GET("repos/{owner}/{repo}/contents") // get all the files and dirs of a repository
Call<List<Files>> getFiles(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@GET("repos/{owner}/{repo}/contents/{file}") // get single file contents
Call<Files> getSingleFileContents(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("file") String file);
@GET("repos/{owner}/{repo}/contents/{fileDir}") // get all the sub files and dirs of a repository
Call<List<Files>> getDirFiles(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("fileDir") String fileDir);
@GET("user/starred/{owner}/{repo}") // check star status of a repository
Call<JsonElement> checkRepoStarStatus(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@PUT("user/starred/{owner}/{repo}") // star a repository
Call<JsonElement> starRepository(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@DELETE("user/starred/{owner}/{repo}") // un star a repository
Call<JsonElement> unStarRepository(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@GET("repos/{owner}/{repo}/subscription") // check watch status of a repository
Call<WatchRepository> checkRepoWatchStatus(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@PUT("repos/{owner}/{repo}/subscription") // watch a repository
Call<JsonElement> watchRepository(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@DELETE("repos/{owner}/{repo}/subscription") // un watch a repository
Call<JsonElement> unWatchRepository(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@GET("repos/{owner}/{repo}/pulls") // get repository pull requests
Call<List<PullRequests>> getPullRequests(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page, @Query("state") String state);
@GET("{owner}/{repo}/pulls/{filename}") // get pull diff file contents
Call<ResponseBody> getFileDiffContents(@Path("owner") String owner, @Path("repo") String repo, @Path("filename") String fileName);
@POST("repos/{owner}/{repo}/pulls/{index}/merge") // merge a pull request
Call<ResponseBody> mergePullRequest(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("index") int index, @Body MergePullRequest jsonStr);
}

View File

@ -0,0 +1,22 @@
package org.mian.gitnex.models;
import java.util.ArrayList;
/**
* Author M M Arif
*/
public class ExploreRepositories {
private ArrayList<UserRepositories> data;
private Boolean ok;
public ArrayList<UserRepositories> getSearchedData() {
return data;
}
public Boolean getOk() {
return ok;
}
}

View File

@ -0,0 +1,39 @@
package org.mian.gitnex.models;
/**
* Author M M Arif
*/
public class FileDiffView {
private String fileName;
private boolean fileType;
private String fileInfo;
private String fileContents;
public FileDiffView(String fileName, boolean fileType, String fileInfo, String fileContents)
{
this.fileName = fileName;
this.fileType = fileType;
this.fileInfo = fileInfo;
this.fileContents = fileContents;
}
public String getFileName() {
return fileName;
}
public boolean isFileType() {
return fileType;
}
public String getFileInfo() {
return fileInfo;
}
public String getFileContents() {
return fileContents;
}
}

View File

@ -0,0 +1,74 @@
package org.mian.gitnex.models;
/**
* Author M M Arif
*/
public class Files {
private String name;
private String path;
private String sha;
private String type;
private int size;
private String encoding;
private String content;
private String target;
private String url;
private String html_url;
private String git_url;
private String download_url;
private String submodule_git_url;
public String getName() {
return name;
}
public String getPath() {
return path;
}
public String getSha() {
return sha;
}
public String getType() {
return type;
}
public int getSize() {
return size;
}
public String getEncoding() {
return encoding;
}
public String getContent() {
return content;
}
public String getTarget() {
return target;
}
public String getUrl() {
return url;
}
public String getHtml_url() {
return html_url;
}
public String getGit_url() {
return git_url;
}
public String getDownload_url() {
return download_url;
}
public String getSubmodule_git_url() {
return submodule_git_url;
}
}

View File

@ -98,10 +98,10 @@ public class Issues {
public class pullRequestObject {
private String merged;
private boolean merged;
private String merged_at;
public String getMerged() {
public boolean isMerged() {
return merged;
}

View File

@ -0,0 +1,19 @@
package org.mian.gitnex.models;
/**
* Author M M Arif
*/
public class MergePullRequest {
private String Do;
private String MergeMessageField;
private String MergeTitleField;
public MergePullRequest(String Do, String MergeMessageField, String MergeTitleField) {
this.Do = Do;
this.MergeMessageField = MergeMessageField;
this.MergeTitleField = MergeTitleField;
}
}

View File

@ -0,0 +1,823 @@
package org.mian.gitnex.models;
import com.google.gson.annotations.SerializedName;
import java.util.Date;
import java.util.List;
/**
* Author M M Arif
*/
public class PullRequests {
private int id;
private String body;
private int comments;
private String diff_url;
private String html_url;
private String merge_base;
private String merge_commit_sha;
private boolean mergeable;
private boolean merged;
private int number;
private String patch_url;
private String state;
private String title;
private String url;
private Date closed_at;
private Date created_at;
private Date due_date;
private Date merged_at;
private Date updated_at;
private userObject user;
private List<labelsObject> labels;
private List<assigneesObject> assignees;
private mergedByObject merged_by;
private milestoneObject milestone;
private baseObject base;
private headObject head;
public PullRequests(String body) {
this.body = body;
}
public class headObject {
private int repo_id;
private String label;
private String ref;
private String sha;
private repoObject repo;
public class repoObject {
private int repo_id;
private boolean allow_merge_commits;
private boolean allow_rebase;
private boolean allow_rebase_explicit;
private boolean allow_squash_merge;
private boolean archived;
private boolean empty;
private boolean fork;
private boolean has_issues;
private boolean has_pull_requests;
private boolean has_wiki;
private boolean ignore_whitespace_conflicts;
@SerializedName("private")
private boolean privateFlag;
private boolean mirror;
private String avatar_url;
private String clone_url;
private String default_branch;
private String description;
private String full_name;
private String html_url;
private String name;
private String ssh_url;
private String website;
private int forks_count;
private int id;
private int open_issues_count;
private int size;
private int stars_count;
private int watchers_count;
private Date created_at;
private Date updated_at;
private ownerObject owner;
private permissionsObject permissions;
public class ownerObject {
private int repo_id;
private boolean is_admin;
private String avatar_url;
private String email;
private String full_name;
private String language;
private String login;
private Date created;
public int getRepo_id() {
return repo_id;
}
public boolean isIs_admin() {
return is_admin;
}
public String getAvatar_url() {
return avatar_url;
}
public String getEmail() {
return email;
}
public String getFull_name() {
return full_name;
}
public String getLanguage() {
return language;
}
public String getLogin() {
return login;
}
public Date getCreated() {
return created;
}
}
public class permissionsObject {
private boolean admin;
private boolean pull;
private boolean push;
public boolean isAdmin() {
return admin;
}
public boolean isPull() {
return pull;
}
public boolean isPush() {
return push;
}
}
public int getRepo_id() {
return repo_id;
}
public boolean isAllow_merge_commits() {
return allow_merge_commits;
}
public boolean isAllow_rebase() {
return allow_rebase;
}
public boolean isAllow_rebase_explicit() {
return allow_rebase_explicit;
}
public boolean isAllow_squash_merge() {
return allow_squash_merge;
}
public boolean isArchived() {
return archived;
}
public boolean isEmpty() {
return empty;
}
public boolean isFork() {
return fork;
}
public boolean isHas_issues() {
return has_issues;
}
public boolean isHas_pull_requests() {
return has_pull_requests;
}
public boolean isHas_wiki() {
return has_wiki;
}
public boolean isIgnore_whitespace_conflicts() {
return ignore_whitespace_conflicts;
}
public boolean isPrivateFlag() {
return privateFlag;
}
public boolean isMirror() {
return mirror;
}
public String getAvatar_url() {
return avatar_url;
}
public String getClone_url() {
return clone_url;
}
public String getDefault_branch() {
return default_branch;
}
public String getDescription() {
return description;
}
public String getFull_name() {
return full_name;
}
public String getHtml_url() {
return html_url;
}
public String getName() {
return name;
}
public String getSsh_url() {
return ssh_url;
}
public String getWebsite() {
return website;
}
public int getForks_count() {
return forks_count;
}
public int getId() {
return id;
}
public int getOpen_issues_count() {
return open_issues_count;
}
public int getSize() {
return size;
}
public int getStars_count() {
return stars_count;
}
public int getWatchers_count() {
return watchers_count;
}
public Date getCreated_at() {
return created_at;
}
public Date getUpdated_at() {
return updated_at;
}
public ownerObject getOwner() {
return owner;
}
public permissionsObject getPermissions() {
return permissions;
}
}
}
public class baseObject {
private int repo_id;
private String label;
private String ref;
private String sha;
private repoObject repo;
public class repoObject {
private int repo_id;
private boolean allow_merge_commits;
private boolean allow_rebase;
private boolean allow_rebase_explicit;
private boolean allow_squash_merge;
private boolean archived;
private boolean empty;
private boolean fork;
private boolean has_issues;
private boolean has_pull_requests;
private boolean has_wiki;
private boolean ignore_whitespace_conflicts;
@SerializedName("private")
private boolean privateFlag;
private boolean mirror;
private String avatar_url;
private String clone_url;
private String default_branch;
private String description;
private String full_name;
private String html_url;
private String name;
private String ssh_url;
private String website;
private int forks_count;
private int id;
private int open_issues_count;
private int size;
private int stars_count;
private int watchers_count;
private Date created_at;
private Date updated_at;
private ownerObject owner;
private permissionsObject permissions;
public class ownerObject {
private int repo_id;
private boolean is_admin;
private String avatar_url;
private String email;
private String full_name;
private String language;
private String login;
private Date created;
public int getRepo_id() {
return repo_id;
}
public boolean isIs_admin() {
return is_admin;
}
public String getAvatar_url() {
return avatar_url;
}
public String getEmail() {
return email;
}
public String getFull_name() {
return full_name;
}
public String getLanguage() {
return language;
}
public String getLogin() {
return login;
}
public Date getCreated() {
return created;
}
}
public class permissionsObject {
private boolean admin;
private boolean pull;
private boolean push;
public boolean isAdmin() {
return admin;
}
public boolean isPull() {
return pull;
}
public boolean isPush() {
return push;
}
}
public int getRepo_id() {
return repo_id;
}
public boolean isAllow_merge_commits() {
return allow_merge_commits;
}
public boolean isAllow_rebase() {
return allow_rebase;
}
public boolean isAllow_rebase_explicit() {
return allow_rebase_explicit;
}
public boolean isAllow_squash_merge() {
return allow_squash_merge;
}
public boolean isArchived() {
return archived;
}
public boolean isEmpty() {
return empty;
}
public boolean isFork() {
return fork;
}
public boolean isHas_issues() {
return has_issues;
}
public boolean isHas_pull_requests() {
return has_pull_requests;
}
public boolean isHas_wiki() {
return has_wiki;
}
public boolean isIgnore_whitespace_conflicts() {
return ignore_whitespace_conflicts;
}
public boolean isPrivateFlag() {
return privateFlag;
}
public boolean isMirror() {
return mirror;
}
public String getAvatar_url() {
return avatar_url;
}
public String getClone_url() {
return clone_url;
}
public String getDefault_branch() {
return default_branch;
}
public String getDescription() {
return description;
}
public String getFull_name() {
return full_name;
}
public String getHtml_url() {
return html_url;
}
public String getName() {
return name;
}
public String getSsh_url() {
return ssh_url;
}
public String getWebsite() {
return website;
}
public int getForks_count() {
return forks_count;
}
public int getId() {
return id;
}
public int getOpen_issues_count() {
return open_issues_count;
}
public int getSize() {
return size;
}
public int getStars_count() {
return stars_count;
}
public int getWatchers_count() {
return watchers_count;
}
public Date getCreated_at() {
return created_at;
}
public Date getUpdated_at() {
return updated_at;
}
public ownerObject getOwner() {
return owner;
}
public permissionsObject getPermissions() {
return permissions;
}
}
}
public class userObject {
private int id;
private String login;
private String full_name;
private String email;
private String avatar_url;
private String language;
private boolean is_admin;
public int getId() {
return id;
}
public String getLogin() {
return login;
}
public String getFull_name() {
return full_name;
}
public String getEmail() {
return email;
}
public String getAvatar_url() {
return avatar_url;
}
public String getLanguage() {
return language;
}
public boolean isIs_admin() {
return is_admin;
}
}
public class labelsObject {
private int id;
private String name;
private String color;
private String url;
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getColor() {
return color;
}
public String getUrl() {
return url;
}
}
public class assigneesObject {
private int id;
private String login;
private String full_name;
private String email;
private String avatar_url;
private String language;
private boolean is_admin;
public int getId() {
return id;
}
public String getLogin() {
return login;
}
public String getFull_name() {
return full_name;
}
public String getEmail() {
return email;
}
public String getAvatar_url() {
return avatar_url;
}
public String getLanguage() {
return language;
}
public boolean isIs_admin() {
return is_admin;
}
}
public class mergedByObject {
private int id;
private String login;
private String full_name;
private String email;
private String avatar_url;
private String language;
private boolean is_admin;
public int getId() {
return id;
}
public String getLogin() {
return login;
}
public String getFull_name() {
return full_name;
}
public String getEmail() {
return email;
}
public String getAvatar_url() {
return avatar_url;
}
public String getLanguage() {
return language;
}
public boolean isIs_admin() {
return is_admin;
}
}
public class milestoneObject {
private int id;
private String title;
private String description;
private String state;
private String open_issues;
private String closed_issues;
private String closed_at;
private String due_on;
public int getId() {
return id;
}
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
public String getState() {
return state;
}
public String getOpen_issues() {
return open_issues;
}
public String getClosed_issues() {
return closed_issues;
}
public String getClosed_at() {
return closed_at;
}
public String getDue_on() {
return due_on;
}
}
public int getId() {
return id;
}
public String getBody() {
return body;
}
public int getComments() {
return comments;
}
public String getDiff_url() {
return diff_url;
}
public String getHtml_url() {
return html_url;
}
public String getMerge_base() {
return merge_base;
}
public String getMerge_commit_sha() {
return merge_commit_sha;
}
public boolean isMergeable() {
return mergeable;
}
public boolean isMerged() {
return merged;
}
public int getNumber() {
return number;
}
public String getPatch_url() {
return patch_url;
}
public String getState() {
return state;
}
public String getTitle() {
return title;
}
public String getUrl() {
return url;
}
public Date getClosed_at() {
return closed_at;
}
public Date getCreated_at() {
return created_at;
}
public Date getDue_date() {
return due_date;
}
public Date getMerged_at() {
return merged_at;
}
public Date getUpdated_at() {
return updated_at;
}
public userObject getUser() {
return user;
}
public List<labelsObject> getLabels() {
return labels;
}
public List<assigneesObject> getAssignees() {
return assignees;
}
public mergedByObject getMerged_by() {
return merged_by;
}
public milestoneObject getMilestone() {
return milestone;
}
public baseObject getBase() {
return base;
}
public headObject getHead() {
return head;
}
}

View File

@ -9,6 +9,7 @@ public class UserTokens {
private int id;
private String name;
private String sha1;
private String token_last_eight;
public UserTokens(String name) {
this.name = name;
@ -29,4 +30,8 @@ public class UserTokens {
public void setName(String name) {
this.name = name;
}
public String getToken_last_eight() {
return token_last_eight;
}
}

View File

@ -0,0 +1,39 @@
package org.mian.gitnex.models;
/**
* Author M M Arif
*/
public class WatchRepository {
private Boolean subscribed;
private Boolean ignored;
private String reason;
private String created_at;
private String url;
private String repository_url;
public Boolean getSubscribed() {
return subscribed;
}
public Boolean getIgnored() {
return ignored;
}
public String getReason() {
return reason;
}
public String getCreated_at() {
return created_at;
}
public String getUrl() {
return url;
}
public String getRepository_url() {
return repository_url;
}
}

View File

@ -13,6 +13,7 @@ import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Locale;
@ -145,16 +146,16 @@ public class AppUtil {
String sMonth;
if (Integer.parseInt(month) < 10) {
sMonth = "0"+String.valueOf(month);
sMonth = "0"+ month;
} else {
sMonth = String.valueOf(month);
sMonth = month;
}
String sDay;
if (Integer.parseInt(day) < 10) {
sDay = "0"+String.valueOf(day);
sDay = "0"+ day;
} else {
sDay = String.valueOf(day);
sDay = day;
}
return year + "-" + sMonth + "-" + sDay;
@ -170,14 +171,14 @@ public class AppUtil {
String sMin;
if ((mMinute) < 10) {
sMin = "0"+String.valueOf(mMinute);
sMin = "0"+ mMinute;
} else {
sMin = String.valueOf(mMinute);
}
String sSec;
if ((mSeconds) < 10) {
sSec = "0"+String.valueOf(mSeconds);
sSec = "0"+ mSeconds;
} else {
sSec = String.valueOf(mSeconds);
}
@ -210,4 +211,30 @@ public class AppUtil {
}
public Boolean sourceCodeExtension(String ext) {
String[] extValues = new String[] {"md", "json", "java", "go", "php", "c", "cc", "cpp", "cxx", "cyc", "m",
"cs", "bash", "sh", "bsh", "cv", "python", "perl", "pm", "rb", "ruby", "javascript",
"coffee", "rc", "rs", "rust", "basic", "clj", "css", "dart", "lisp", "erl", "hs", "lsp", "rkt",
"ss", "llvm", "ll", "lua", "matlab", "pascal", "r", "scala", "sql", "latex", "tex", "vb", "vbs",
"vhd", "tcl", "wiki.meta", "yaml", "yml", "markdown", "xml", "proto", "regex", "py", "pl", "js",
"html", "htm", "volt", "ini", "htaccess", "conf", "gitignore", "gradle", "txt", "properties", "bat"};
return Arrays.asList(extValues).contains(ext);
}
public Boolean imageExtension(String ext) {
String[] extValues = new String[] {"jpg", "jpeg", "gif", "png", "ico"};
return Arrays.asList(extValues).contains(ext);
}
public String getLastCharactersOfWord( String str, int count ) {
return str.substring(str.length() - count);
}
}

View File

@ -35,7 +35,7 @@ public class AdminGetUsersViewModel extends ViewModel {
public static void loadUsersList(final Context ctx, String instanceUrl, String token) {
Call<List<UserInfo>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, ctx)
.getApiInterface()
.adminGetUsers(token);

View File

@ -1,5 +1,6 @@
package org.mian.gitnex.viewmodels;
import android.content.Context;
import android.util.Log;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.models.Branches;
@ -20,18 +21,18 @@ public class BranchesViewModel extends ViewModel {
private static MutableLiveData<List<Branches>> branchesList;
public LiveData<List<Branches>> getBranchesList(String instanceUrl, String token, String owner, String repo) {
public LiveData<List<Branches>> getBranchesList(String instanceUrl, String token, String owner, String repo, Context ctx) {
branchesList = new MutableLiveData<>();
loadBranchesList(instanceUrl, token, owner, repo);
loadBranchesList(instanceUrl, token, owner, repo, ctx);
return branchesList;
}
public static void loadBranchesList(String instanceUrl, String token, String owner, String repo) {
public static void loadBranchesList(String instanceUrl, String token, String owner, String repo, Context ctx) {
Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getBranches(token, owner, repo);

View File

@ -1,5 +1,6 @@
package org.mian.gitnex.viewmodels;
import android.content.Context;
import android.util.Log;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.models.Collaborators;
@ -20,18 +21,18 @@ public class CollaboratorsViewModel extends ViewModel {
private static MutableLiveData<List<Collaborators>> collaboratorsList;
public LiveData<List<Collaborators>> getCollaboratorsList(String instanceUrl, String token, String owner, String repo) {
public LiveData<List<Collaborators>> getCollaboratorsList(String instanceUrl, String token, String owner, String repo, Context ctx) {
collaboratorsList = new MutableLiveData<>();
loadCollaboratorsListList(instanceUrl, token, owner, repo);
loadCollaboratorsListList(instanceUrl, token, owner, repo, ctx);
return collaboratorsList;
}
private static void loadCollaboratorsListList(String instanceUrl, String token, String owner, String repo) {
private static void loadCollaboratorsListList(String instanceUrl, String token, String owner, String repo, Context ctx) {
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getCollaborators(token, owner, repo);

View File

@ -0,0 +1,117 @@
package org.mian.gitnex.viewmodels;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Files;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class FilesViewModel extends ViewModel {
private static MutableLiveData<List<Files>> filesList;
private static MutableLiveData<List<Files>> filesList2;
public LiveData<List<Files>> getFilesList(String instanceUrl, String token, String owner, String repo, Context ctx) {
filesList = new MutableLiveData<>();
loadFilesList(instanceUrl, token, owner, repo, ctx);
return filesList;
}
private static void loadFilesList(String instanceUrl, String token, String owner, String repo, final Context ctx) {
Call<List<Files>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getFiles(token, owner, repo);
call.enqueue(new Callback<List<Files>>() {
@Override
public void onResponse(@NonNull Call<List<Files>> call, @NonNull Response<List<Files>> response) {
if (response.isSuccessful()) {
Collections.sort(response.body(), new Comparator<Files>() {
@Override
public int compare(Files byType1, Files byType2) {
return byType1.getType().compareTo(byType2.getType());
}
});
filesList.postValue(response.body());
} else {
Toasty.info(ctx, ctx.getString(R.string.noDataFilesTab));
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Files>> call, Throwable t) {
Log.i("onFailure", t.toString());
}
});
}
public LiveData<List<Files>> getFilesList2(String instanceUrl, String token, String owner, String repo, String filesDir, Context ctx) {
filesList2 = new MutableLiveData<>();
loadFilesList2(instanceUrl, token, owner, repo, filesDir, ctx);
return filesList2;
}
private static void loadFilesList2(String instanceUrl, String token, String owner, String repo, String filesDir, final Context ctx) {
Call<List<Files>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getDirFiles(token, owner, repo, filesDir);
call.enqueue(new Callback<List<Files>>() {
@Override
public void onResponse(@NonNull Call<List<Files>> call, @NonNull Response<List<Files>> response) {
if (response.isSuccessful()) {
Collections.sort(response.body(), new Comparator<Files>() {
@Override
public int compare(Files byType1, Files byType2) {
return byType1.getType().compareTo(byType2.getType());
}
});
filesList2.postValue(response.body());
} else {
Toasty.info(ctx, ctx.getString(R.string.noDataFilesTab));
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Files>> call, Throwable t) {
Log.i("onFailure", t.toString());
}
});
}
}

View File

@ -1,5 +1,6 @@
package org.mian.gitnex.viewmodels;
import android.content.Context;
import android.util.Log;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.models.IssueComments;
@ -20,18 +21,18 @@ public class IssueCommentsViewModel extends ViewModel {
private static MutableLiveData<List<IssueComments>> issueComments;
public LiveData<List<IssueComments>> getIssueCommentList(String instanceUrl, String token, String owner, String repo, int index) {
public LiveData<List<IssueComments>> getIssueCommentList(String instanceUrl, String token, String owner, String repo, int index, Context ctx) {
issueComments = new MutableLiveData<>();
loadIssueComments(instanceUrl, token, owner, repo, index);
loadIssueComments(instanceUrl, token, owner, repo, index, ctx);
return issueComments;
}
public static void loadIssueComments(String instanceUrl, String token, String owner, String repo, int index) {
public static void loadIssueComments(String instanceUrl, String token, String owner, String repo, int index, Context ctx) {
Call<List<IssueComments>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getIssueComments(token, owner, repo, index);

View File

@ -1,5 +1,6 @@
package org.mian.gitnex.viewmodels;
import android.content.Context;
import android.util.Log;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.models.Labels;
@ -20,18 +21,18 @@ public class LabelsViewModel extends ViewModel {
private static MutableLiveData<List<Labels>> labelsList;
public LiveData<List<Labels>> getLabelsList(String instanceUrl, String token, String owner, String repo) {
public LiveData<List<Labels>> getLabelsList(String instanceUrl, String token, String owner, String repo, Context ctx) {
labelsList = new MutableLiveData<>();
loadLabelsList(instanceUrl, token, owner, repo);
loadLabelsList(instanceUrl, token, owner, repo, ctx);
return labelsList;
}
public static void loadLabelsList(String instanceUrl, String token, String owner, String repo) {
public static void loadLabelsList(String instanceUrl, String token, String owner, String repo, Context ctx) {
Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getlabels(token, owner, repo);

View File

@ -1,5 +1,6 @@
package org.mian.gitnex.viewmodels;
import android.content.Context;
import android.util.Log;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.models.UserInfo;
@ -20,18 +21,18 @@ public class MembersByOrgViewModel extends ViewModel {
private static MutableLiveData<List<UserInfo>> membersList;
public LiveData<List<UserInfo>> getMembersList(String instanceUrl, String token, String owner) {
public LiveData<List<UserInfo>> getMembersList(String instanceUrl, String token, String owner, Context ctx) {
membersList = new MutableLiveData<>();
loadMembersList(instanceUrl, token, owner);
loadMembersList(instanceUrl, token, owner, ctx);
return membersList;
}
private static void loadMembersList(String instanceUrl, String token, String owner) {
private static void loadMembersList(String instanceUrl, String token, String owner, Context ctx) {
Call<List<UserInfo>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getMembersByOrg(token, owner);

Some files were not shown because too many files have changed in this diff Show More