Compare commits

..

325 Commits

Author SHA1 Message Date
7317f3c841 Merge pull request 'Prepare 2.4.1 release' (#301) from prepare-release-2.4.1 into release-2.4
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/301
2020-03-19 13:24:47 +00:00
8b12e51335 Prepare 2.4.1 release 2020-03-19 18:22:37 +05:00
086f982d26 Merge pull request 'Backport show only issues, use StandardCharsets instead in okhttp' (#300) from backport-show-only-issues into release-2.4
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/300
2020-03-19 13:16:55 +00:00
88feca3564 Backport show only issues, use StandardCharsets instead in okhttp 2020-03-19 18:14:13 +05:00
40337d10b4 Merge pull request 'fixed #297 in release-2.4 branch' (#299) from a671916c/GitNex:release-2.4 into release-2.4
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/299
Reviewed-by: M M Arif <mmarif@swatian.com>
2020-03-18 18:43:37 +00:00
05056f28ac fixed #297 in release-2.4 branch 2020-03-18 19:32:56 +01:00
94af921a99 Merge pull request 'Fix files breadcrumb nav' (#289) from 287-fix-files-breadcrumb into release-2.4
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/289
2020-03-16 14:47:03 +00:00
ac3cc11920 Fix files breadcrumb nav 2020-03-16 19:40:46 +05:00
23c8bb3a48 Merge pull request 'crowdin update' (#285) from 6543/GitNex:backport_284 into release-2.4
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/285
Reviewed-by: M M Arif <mmarif@swatian.com>
2020-03-15 18:46:52 +00:00
8c97160737 crowdin update 2020-03-15 19:40:47 +01:00
c47c81e71f Prepare release 2.4.0 (#283)
Remove Translucent background

Fix missing theme colors, layouts using standard

Fix toolbar color

Prepare 2.4.0 release

Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/283
2020-03-15 15:09:26 +00:00
c981ec2f16 Fixes for 2.4 release (#281)
Fix unnecessary reset for repositories

merge screen background color

Merge branch 'master' into fixes-2.4

Add bottom margin for smaller devices

Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/281
2020-03-14 14:22:50 +00:00
26429ca6e7 Crowdin [2020-03-11] (#277)
update

update from crowdin

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/277
2020-03-13 19:51:29 +00:00
d06a439382 Merge pull request 'Add page and limit params to required API calls' (#279) from 273-add-page-limit-param into master
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/279
2020-03-13 19:30:11 +00:00
e7433fd67d Merge pull request '[Fileviewer] Download files, Don't render specific files' (#275) from 254-download-files into master
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/275
2020-03-13 19:29:24 +00:00
0467686cc3 Enhance diff view to not render all files (#274)
Merge branch 'master' into 269-dont-render-files

exlucde certain bin files

Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/274
2020-03-13 19:28:29 +00:00
b0d5161c22 Merge pull request 'fix background color' (#280) from fixes-2.4 into master
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/280
2020-03-13 14:32:57 +00:00
64839fdc44 fix background color 2020-03-13 19:30:43 +05:00
d441833952 Add page and limit params to required API calls 2020-03-12 19:56:56 +05:00
a2672560da Merge branch 'master' into 254-download-files 2020-03-11 15:29:37 +00:00
f7d5ee9e7a Update for issue 267 2020-03-09 21:13:40 +05:00
3a481084b6 Merge branch 'master' into 254-download-files
# Conflicts:
#	app/src/main/java/org/mian/gitnex/activities/FileViewActivity.java
2020-03-08 19:24:41 +05:00
4ac1f4f486 Single issue ui enhancements (#272)
Merge branch 'master' into 270-single-issue-ui-enhancements

improve single issue title

Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/272
Reviewed-by: 6543 <6543@noreply.gitea.io>
2020-03-08 14:14:46 +00:00
d2f5f09c75 Merge pull request 'Theme and Icons' (#260) from light-theme into master
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/260
Reviewed-by: 6543 <6543@noreply.gitea.io>
2020-03-08 13:52:25 +00:00
181a94edbe download file and ask for permissions to write into storage 2020-03-08 12:46:31 +05:00
5b8c485883 Fix variable name 2020-03-08 10:54:33 +05:00
3794d7ff2b wip on download files 2020-03-08 10:53:00 +05:00
9a9b836c40 Fix file diff background 2020-03-07 13:30:45 +05:00
900b060c31 Use only one statement for new theme. 2020-03-07 01:07:54 +05:00
61f953d70d Fixes layout issue with themes, added pdf night mode switch in settings 2020-03-06 18:46:22 +05:00
14addf5ed0 added theme selection to settings, updated login layout. 2020-03-06 01:56:42 +05:00
b012a7058d Fixes to color styles and layouts 2020-03-05 20:23:15 +05:00
51ab3f7a92 updated all the layouts and activities 2020-03-05 00:37:28 +05:00
a8cc4c00b8 worked on repo info, files tabs and files activity 2020-03-04 21:15:57 +05:00
d557999a38 Merge branch 'master' into light-theme 2020-03-04 19:58:03 +05:00
1008b8611d Added custom attr to more files 2020-03-04 19:54:21 +05:00
3f4db112b1 Refactor assignee(s) API calls (#199)
Merge branch 'master' into refactor_issues_call

Remove credits, add donators (#268)

Merge branch 'master' into 264-remove-credits

Merge pull request 'Support for c header files' (#266) from 265-files-support-in-file-viewer into master

Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/266

Remove credits, add donators

support for c header files

Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/268

Merge pull request 'Support for c header files' (#266) from 265-files-support-in-file-viewer into master

Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/266

support for c header files

fix

Merge branch 'master' into refactor_issues_call

Support pdf files in file viewer (#259)

auto convert EOL

this fix it for me

fix layout

implement support for pdf files in file viewer

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/259
Reviewed-by: 6543 <6543@noreply.gitea.io>

Make DueDate optional on MilestoneCreaton (#252)

Merge branch 'master' into milestone-DueDate-optional_240

add check again if gitea is older than 1.10.0 ...

Crowdin [2020-01-04] + add Latvian (#253)

update Translators

add Latvian

update Crowdin

Co-authored-by: 6543 <6543@obermui.de>

make DueDate optional on MilestoneCreaton

Co-authored-by: 6543 <6543@obermui.de>

Crowdin [2020-01-04] + add Latvian (#253)

update Translators

add Latvian

update Crowdin

Co-authored-by: 6543 <6543@obermui.de>

Merge branch '51-custom-fonts' of gitnex/GitNex into master

Reviewed-by: 6543 <6543@noreply.gitea.io>

Implement across the whole app

Implementation of custom fonts app wide

Merge branch 'crowdin_2019-12-25' of gitnex/GitNex into master

add user to the “new issue” assignees dialog

refactor.start()

update from crowdin

Merge branch 'backport-243' of gitnex/GitNex into master

backport url slashes fix

Merge branch 'fix-238' of gitnex/GitNex into master

fix

Merge branch 'backport-235' of gitnex/GitNex into master

backport fix #235

Merge branch 'backport-232' of gitnex/GitNex into master

show all issues and prs

Merge branch '206-repos-in-explore-screen' of gitnex/GitNex into master

Load default list of explore repositories

Merge branch '225-backport' of gitnex/GitNex into master

copy and support files backport - #225

Merge branch '226-backport' of gitnex/GitNex into master

fix alignments backport

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/199
2020-02-24 18:50:51 +00:00
5720c5f613 Remove credits, add donators (#268)
Merge branch 'master' into 264-remove-credits

Merge pull request 'Support for c header files' (#266) from 265-files-support-in-file-viewer into master

Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/266

Remove credits, add donators

support for c header files

Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/268
2020-02-21 05:58:36 +00:00
e0b25c77a0 Merge pull request 'Support for c header files' (#266) from 265-files-support-in-file-viewer into master
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/266
2020-02-21 05:54:53 +00:00
2c163fdc9c support for c header files 2020-02-20 10:24:14 +05:00
acdb9ce682 updates to other files 2020-02-20 10:19:52 +05:00
dbcd80eace updated settings, star and my repos layouts 2020-02-04 19:19:39 +05:00
8b75cac9d8 New spinner style 2020-02-03 00:14:38 +05:00
1293e8be27 Support pdf files in file viewer (#259)
auto convert EOL

this fix it for me

fix layout

implement support for pdf files in file viewer

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/259
Reviewed-by: 6543 <6543@noreply.gitea.io>
2020-01-30 18:00:31 +00:00
50671907ba changed checkbox style and input background 2020-01-29 19:31:27 +05:00
ec62e3cebf Make DueDate optional on MilestoneCreaton (#252)
Merge branch 'master' into milestone-DueDate-optional_240

add check again if gitea is older than 1.10.0 ...

Crowdin [2020-01-04] + add Latvian (#253)

update Translators

add Latvian

update Crowdin

Co-authored-by: 6543 <6543@obermui.de>

make DueDate optional on MilestoneCreaton

Co-authored-by: 6543 <6543@obermui.de>
2020-01-14 12:52:34 +00:00
36774620db initial work on adding new theme 2020-01-07 17:27:05 +05:00
b3e67113f5 Crowdin [2020-01-04] + add Latvian (#253)
update Translators

add Latvian

update Crowdin

Co-authored-by: 6543 <6543@obermui.de>
2020-01-05 12:07:29 +00:00
d8de0effef Merge branch '51-custom-fonts' of gitnex/GitNex into master
Reviewed-by: 6543 <6543@noreply.gitea.io>
2020-01-02 14:40:28 +00:00
0533fd9ae5 Implement across the whole app 2020-01-02 12:51:10 +05:00
6d7308210b Implementation of custom fonts app wide 2020-01-02 01:03:53 +05:00
e9dcfc57f7 Merge branch 'crowdin_2019-12-25' of gitnex/GitNex into master 2019-12-26 02:07:36 +00:00
ab6f5d3364 update from crowdin 2019-12-25 20:48:52 +01:00
e422e3e254 Merge branch 'backport-243' of gitnex/GitNex into master 2019-12-25 19:18:17 +00:00
a00d76d0e2 backport url slashes fix 2019-12-26 00:14:33 +05:00
f68c26b70d Merge branch 'fix-238' of gitnex/GitNex into master 2019-12-24 19:22:14 +00:00
25cc2f27ee fix 2019-12-24 17:09:24 +01:00
72ccc06226 Merge branch 'backport-235' of gitnex/GitNex into master 2019-12-13 13:38:09 +00:00
9a66ea0fb6 backport fix #235 2019-12-13 13:55:58 +05:00
aab9ae9e35 Merge branch 'backport-232' of gitnex/GitNex into master 2019-12-04 18:41:19 +00:00
d922c21f70 show all issues and prs 2019-12-04 23:38:53 +05:00
6e02fc1827 Merge branch '206-repos-in-explore-screen' of gitnex/GitNex into master 2019-12-03 16:27:18 +00:00
536665be5f Load default list of explore repositories 2019-12-03 18:20:26 +05:00
29cc8a2ad4 Merge branch '225-backport' of gitnex/GitNex into master 2019-12-02 15:00:37 +00:00
7d4d7cfa69 copy and support files backport - #225 2019-12-02 19:58:36 +05:00
48638e93be Merge branch '226-backport' of gitnex/GitNex into master 2019-12-02 14:55:12 +00:00
584c08ff70 fix alignments backport 2019-12-02 19:52:11 +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
7abfdc9567 Merge branch 'fix-old-gitea-api' of mmarif/GitNex into release-2.1 2019-10-03 19:03:06 +00:00
0ab8784a7a another quick release and another old Gitea instances issue 2019-10-04 00:00:05 +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
22b3802e73 Merge branch 'fixes-2.1.2' of mmarif/GitNex into release-2.1 2019-10-03 16:45:36 +00:00
07a1fa6aad Fix crashes on my repo, starred repos etc - 2.1.2 release 2019-10-03 21:43:33 +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
4904b5899f Merge branch 'fixes-2.1' of mmarif/GitNex into release-2.1 2019-10-02 17:26:30 +00:00
f19327431f fix bugs since 2.1.0 release 2019-10-02 22:24:02 +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
8b26355fc0 Merge branch 'prepare-release' of mmarif/GitNex into master 2019-10-01 15:35:05 +00:00
8effad46f8 app release 2.1.0 2019-10-01 20:31:01 +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
53efd8b777 Merge branch '79-repo-avatar' of mmarif/GitNex into master 2019-10-01 13:59:59 +00:00
19cd5b6c5e added repos avatars 2019-10-01 18:56:20 +05:00
69082b424a Merge branch '54-enable-disable-create-issue' of mmarif/GitNex into master 2019-10-01 13:07:58 +00:00
d8b3477940 check if repo issues is enalbed or disabled 2019-10-01 18:05:09 +05:00
34892e7f43 Merge branch 'fix-ms-bar' of mmarif/GitNex into master 2019-10-01 10:26:03 +00:00
d64b035d4a fix ms progress bar 2019-10-01 15:23:49 +05:00
e2fa79b2a9 Merge branch 'master' of gitea.com:mmarif/GitNex 2019-10-01 15:06:46 +05:00
9e658aa38c 63-ms-ui (#82) 2019-10-01 10:05:26 +00:00
e4700ffd69 Merge branch 'master' of gitea.com:mmarif/GitNex 2019-10-01 11:44:45 +05:00
e53ef41fc1 ui-improvements (#81) 2019-10-01 06:42:56 +00:00
c05e69cfe9 t 2019-10-01 10:23:50 +05:00
5c6d5177fb r 2019-10-01 10:14:54 +05:00
62a5452437 Merge branch 'master' of gitea.com:mmarif/GitNex
# Conflicts:
#	app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java
#	app/src/main/java/org/mian/gitnex/activities/MainActivity.java
#	app/src/main/java/org/mian/gitnex/adapters/AdminGetUsersAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/CollaboratorsAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/IssueCommentsAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/MembersByOrgAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/MyReposListAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/OrganizationsListAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/ProfileFollowersAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/ProfileFollowingAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/ReposListAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/RepositoriesByOrgAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/StarredReposListAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/TeamMembersByOrgAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/UserSearchAdapter.java
#	app/src/main/java/org/mian/gitnex/fragments/OrganizationInfoFragment.java
#	app/src/main/java/org/mian/gitnex/fragments/ProfileFragment.java
#	app/src/main/res/layout/activity_issue_detail.xml
#	app/src/main/res/layout/admin_users_list.xml
#	app/src/main/res/layout/fragment_profile.xml
#	app/src/main/res/layout/issue_comments.xml
#	app/src/main/res/layout/my_repos_list.xml
#	app/src/main/res/layout/nav_header.xml
#	app/src/main/res/layout/organizations_list.xml
#	app/src/main/res/layout/profile_followers_list.xml
#	app/src/main/res/layout/profile_following_list.xml
#	app/src/main/res/layout/repos_list.xml
#	app/src/main/res/layout/repositories_by_org_list.xml
#	app/src/main/res/layout/starred_repos_list.xml
2019-10-01 10:14:45 +05:00
5f402c2c60 merge 2019-10-01 10:12:18 +05:00
85140fbee0 Merge branch '77-ui-changes' of mmarif/GitNex into master 2019-09-30 18:16:24 +00:00
d350fe96d9 Merge branch 'master' into 77-ui-changes 2019-09-30 23:14:04 +05:00
61a1a4446f Merge branch '62-improve-issues-ui' of mmarif/GitNex into master 2019-09-30 18:09:47 +00:00
c1e27c9776 Merge branch 'issue-copy-nr' of 6543/GitNex into master 2019-09-30 18:07:25 +00:00
03ec591643 more ui changes 2019-09-30 22:48:52 +05:00
3ebc1ae3e0 avatars improvements 2019-09-30 22:39:33 +05:00
3c8fb5bc60 markdown code cleanup 2019-09-30 21:21:51 +05:00
5503fe9951 Redid the issues list ui and some clean up 2019-09-30 21:12:45 +05:00
7f417da6b3 update libs, switch to io.notis for md. refactor all the markdown code 2019-09-29 21:44:42 +05:00
4e8a961643 copyIssue -> copyIssueUrl 2019-09-29 00:56:48 +02:00
bf5527a82d issue -> issueUrl 2019-09-29 00:10:28 +02:00
c31cf53023 Merge branch 'milestoneProgress' of 6543/GitNex into master 2019-09-28 18:15:41 +00:00
0ac2a27549 all milestones look similar 2019-09-27 23:58:23 +02:00
dcabfa4f14 add Progress Bar function 2019-09-27 23:32:31 +02:00
9688c75106 add progress bar to layout 2019-09-27 22:52:29 +02:00
71bb8cc75d add copy function 2019-09-27 21:17:28 +02:00
dcd28e845a add Copy to Clipboard String 2019-09-27 19:12:19 +02:00
b3e88b0a9d add content copy icon 2019-09-27 18:50:05 +02:00
ce67f59753 Merge branch '67-filter-icon' of mmarif/GitNex into master 2019-09-26 19:09:16 +00:00
d0b6730de4 change search icon/text to filter 2019-09-26 23:58:36 +05:00
f5e18ed5cc Merge branch 'dl-apk-buton' of 6543/GitNex into master 2019-09-23 18:38:31 +00:00
88394e1c25 Merge branch 'translate_german' of IndeedNotJames/GitNex into master 2019-09-23 18:19:01 +00:00
a9030eb8c9 Bump requred Gitea Version 2019-09-22 18:05:54 +02:00
fff307d45a test look 2019-09-22 17:48:41 +02:00
b64ee37edd add release badge 2019-09-22 17:40:18 +02:00
b4b3c2f5ee add download apk sing from website 2019-09-22 16:49:07 +02:00
8f3ef29f44 complete german translation 2019-09-21 20:50:33 +02:00
d00691d71b Merge branch 'new-font-testing' of mmarif/GitNex into master 2019-09-19 06:35:28 +00:00
4867524b4f Merge branch 'master' into new-font-testing 2019-09-19 11:28:07 +05:00
a59e818aa2 Merge branch 'master' into new-font-testing 2019-09-19 11:27:09 +05:00
aeca4a0edb Merge branch 'fix-open-issue-tab' of mmarif/GitNex into master 2019-09-19 06:22:57 +00:00
2c60f092f1 Fix open issues tab color bug, dim color for info tab headers 2019-09-19 11:21:15 +05:00
fe0b3a77cc Merge branch 'minor-enhancements' of mmarif/GitNex into master 2019-09-19 05:38:26 +00:00
43c014948a Repo label and info tabs fixes 2019-09-19 10:36:55 +05:00
a497e0a284 new font 2019-09-19 10:10:12 +05:00
da268b017e Merge branch 'prepare-2-0-release' of mmarif/GitNex into master 2019-09-18 10:27:06 +00:00
4451adb01c prepare for release 2019-09-18 15:02:33 +05:00
0cd4e36a66 Merge branch '16-create-files' of mmarif/GitNex into master 2019-09-18 09:51:27 +00:00
742b1894e6 finished work on creating new file 2019-09-18 14:49:29 +05:00
8d1b47de8e wip on creating new file. still has to do branches section for old and new. 2019-09-18 13:25:49 +05:00
c38d249571 new file layout and bottomsheet link 2019-09-17 11:17:05 +05:00
c3da1900a0 add donator to sponsor page, file icon 2019-09-17 09:24:32 +05:00
b4c0745b40 reduce large links in branches and releases to small text with links.
Signed-off-by: M M Arif <mmarif@swatian.com>
2019-09-16 20:28:34 +05:00
e8e0cf904b Merge branch '37-fix-crash-within-tabs' of mmarif/GitNex into master 2019-09-14 09:43:54 +00:00
99718bc0c8 fix branches hash url 2019-09-14 14:40:47 +05:00
d4a5d5ee8c fix url linking for repo website 2019-09-14 13:22:01 +05:00
efffc05a89 fix crash on tabs, other ui fixes 2019-09-14 13:20:00 +05:00
a78018fd08 Merge branch '36-open-repo-in-browser' of mmarif/GitNex into master 2019-09-14 07:41:00 +00:00
33d1373f6e added open in browser 2019-09-14 12:38:41 +05:00
b15394e97d Add browser icon and xml element in menu 2019-09-14 12:26:20 +05:00
2bdeee5429 Merge branch '24-list-repo-watchers' of mmarif/GitNex into master 2019-09-14 06:55:22 +00:00
39c1ec36a7 Added repo watchers/subscribrs list 2019-09-14 11:29:20 +05:00
6866154714 Merge branch '25-list-repo-stargazers' of mmarif/GitNex into master 2019-09-13 16:03:29 +00:00
df260f05d2 added stargazers and other fixes and enhancements 2019-09-13 20:56:30 +05:00
d24e7ffc3b Add dotted menu 2019-09-13 12:21:52 +05:00
481451c791 Merge branch '23-fixes' of mmarif/GitNex into master 2019-09-12 08:32:00 +00:00
914d5cfa26 libs update, fixes search tap crashing. remove depricated classes 2019-09-12 13:30:07 +05:00
6710aa0810 clean up unwanted namespaces from layouts 2019-09-12 10:29:41 +05:00
87376a2104 Fix collaborator not found text 2019-09-12 10:21:53 +05:00
1ec7ac4f9f Merge branch 'open-repo-web' of 6543/GitNex into master 2019-09-11 06:26:58 +00:00
25f8277f0a translate missing with deepl 2019-09-10 19:56:54 +02:00
498bf7a72c spelling corection 2019-09-10 19:51:43 +02:00
20f687e30e add sugestions of mmarif
* delete OpenWebRepoActivity (function is handled in RepoDetailActivity )
 * add&handle case "openWebRepo" in RepoDetailActivity
 * add new Value "instanceUrlWithProtocol" to tinyDb
2019-09-10 19:48:44 +02:00
83e3564c13 try to implement OpenWebRepoActivity 2019-09-06 01:01:46 +02:00
7977aaa2be shorter text 2019-09-05 22:19:26 +02:00
6bc13ad4fe ues language icon also to indicate webbrowser open action 2019-09-05 22:06:23 +02:00
1f6f50977e Merge branch 'german-translation' of 6543/GitNex into master 2019-09-05 10:09:51 +00:00
1ce1278095 tiny lang. changes 2019-09-03 16:55:51 +02:00
ce63cde4ee add menue entry and strings 2019-09-03 16:46:38 +02:00
f23c4074f3 Merge branch 'master' of PsychotherapistSam/GitNex into master 2019-07-18 10:43:17 +00:00
ace9111225 Update 'app/src/main/res/values-de/strings.xml'
Updated some of the german translations :)
2019-07-18 03:44:16 +00:00
4aeeb95308 Merge branch 'fix-contribute-file' of mmarif/GitNex into master 2019-06-24 10:04:55 +00:00
056413e0b0 fix wordings 2019-06-24 02:33:30 +05:00
389 changed files with 17621 additions and 3537 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

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
* text=auto eol=lf

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

@ -3,14 +3,14 @@
Please take a few minutes to read this document to make the process of contribution more easy and healthy for all involved.
## Pull Requests
Patches, enhancements, features are always welcome. The MR should focus on the scope of work and avoid many unnecessary commits. Please provide as much detail and context as possible to explain the work submitted.
Patches, enhancements, features are always welcome. The PR should focus on the scope of work and avoid many unnecessary commits. Please provide as much detail and context as possible to explain the work submitted.
Please ask if you are not sure about the scope of work to be submitted to avoid waste of time spent on the work.
**How to submit MR/PR**
**How to submit a PR**
Fork this repository. Pull the forked repository from your namespace to your local machine. Create new branch and work on the bug/feature/enhancement you would like to submit. Push it to your forked version. From there create Pull Request(PR) against **master** branch.
**IMPORTANT:** By submitting MR, you agree to allow GitNex to license your work under the same license as that used by GitNex.
**IMPORTANT:** By submitting PR, you agree to allow GitNex to license your work under the same license as that used by GitNex.
## Issues and Reports
*1st of please be polite and gentle while commenting or creating new issue to maintain a healthy environment.*
@ -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).

36
CONTRIBUTORS.md Normal file
View File

@ -0,0 +1,36 @@
# 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
* Lafriks
* 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,6 +1,10 @@
[![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/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"/>](https://liberapay.com/mmarif/donate)
[<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)
# GitNex - Android client for Gitea
@ -10,12 +14,14 @@ GitNex is licensed under GPLv3 License. See the LICENSE file for the full licens
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) [Download APK](https://gitea.com/mmarif/GitNex/releases)
[<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/gitnex/GitNex/releases)
## Note about Gitea version
Please make sure that you are on Gitea **1.7.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 latest stable release or later for better app experience.
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.
@ -23,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.
@ -65,5 +83,12 @@ 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
- Barteksc/AndroidPdfViewer
[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 45
versionName "1.5.0"
targetSdkVersion 29
versionCode 91
versionName "2.4.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@ -23,45 +23,51 @@ android {
}
dependencies {
def lifecycle_version = "2.2.0-alpha01"
final def markwon_version = "3.0.0"
def lifecycle_version = "2.2.0"
final def markwon_version = "4.1.1"
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.1.0-beta01'
implementation 'com.google.android.material:material:1.1.0-alpha07'
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-alpha05"
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 "ru.noties.markwon:core:$markwon_version"
implementation "ru.noties.markwon:ext-strikethrough:$markwon_version"
implementation "ru.noties.markwon:ext-tables:$markwon_version"
implementation "ru.noties.markwon:ext-tasklist:$markwon_version"
implementation "ru.noties.markwon:syntax-highlight:$markwon_version"
implementation "ru.noties.markwon:image-okhttp:$markwon_version"
implementation "ru.noties.markwon:html:$markwon_version"
implementation "ru.noties.markwon:recycler:$markwon_version"
implementation "ru.noties.markwon:recycler-table:$markwon_version"
implementation "ru.noties.markwon:image-gif:$markwon_version"
implementation "ru.noties.markwon:image-svg:$markwon_version"
implementation "io.noties.markwon:core:$markwon_version"
implementation "io.noties.markwon:ext-latex:$markwon_version"
implementation "io.noties.markwon:ext-strikethrough:$markwon_version"
implementation "io.noties.markwon:ext-tables:$markwon_version"
implementation "io.noties.markwon:ext-tasklist:$markwon_version"
implementation "io.noties.markwon:html:$markwon_version"
implementation "io.noties.markwon:image:$markwon_version"
implementation "io.noties.markwon:image-picasso:$markwon_version"
implementation "io.noties.markwon:linkify:$markwon_version"
implementation "io.noties.markwon:recycler:$markwon_version"
implementation "io.noties.markwon:recycler-table:$markwon_version"
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.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"
implementation "com.github.barteksc:android-pdf-viewer:3.2.0-beta.1"
}

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.mian.gitnex">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
@ -12,8 +14,21 @@
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/app_logo_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".activities.AdminGetUsersActivity"></activity>
tools:targetApi="n">
<activity android:name=".activities.MergePullRequestActivity" />
<activity
android:name=".activities.FileViewActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.NewFileActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.RepoWatchersActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.RepoStargazersActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".activities.AdminGetUsersActivity" />
<activity
android:name=".activities.AddRemoveAssigneesActivity"
android:theme="@style/Theme.AppCompat.Light.Dialog" />
@ -44,7 +59,7 @@
android:name=".activities.RepoDetailActivity"
android:label="@string/title_activity_repo_detail"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".activities.MainActivity">
<activity android:name=".activities.MainActivity" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -56,6 +71,8 @@
android:launchMode="singleTask" />
<activity android:name=".activities.NewRepoActivity" />
<activity android:name=".activities.NewOrganizationActivity" />
<activity android:name=".activities.OpenRepoInBrowserActivity" />
<activity android:name=".activities.FileDiffActivity" />
</application>
</manifest>

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -23,7 +22,6 @@ 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;
@ -31,7 +29,7 @@ import java.util.List;
* Author M M Arif
*/
public class AddCollaboratorToRepositoryActivity extends AppCompatActivity {
public class AddCollaboratorToRepositoryActivity extends BaseActivity {
private View.OnClickListener onClickListener;
final Context ctx = this;
@ -42,11 +40,13 @@ public class AddCollaboratorToRepositoryActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_collaborator_to_repository);
protected int getLayoutResourceId(){
return R.layout.activity_add_collaborator_to_repository;
}
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
@ -81,7 +81,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 +101,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

@ -1,13 +1,11 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
@ -18,7 +16,7 @@ import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.MultiSelectModel;
import org.mian.gitnex.models.UpdateIssueAssignee;
import org.mian.gitnex.models.UpdateIssueAssignees;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
@ -29,7 +27,7 @@ import retrofit2.Callback;
* Author M M Arif
*/
public class AddRemoveAssigneesActivity extends AppCompatActivity {
public class AddRemoveAssigneesActivity extends BaseActivity {
private ArrayList<MultiSelectModel> listOfCollaborators = new ArrayList<>();
private ArrayList<Integer> issueAssigneesIds = new ArrayList<>();
@ -38,11 +36,15 @@ public class AddRemoveAssigneesActivity extends AppCompatActivity {
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_add_remove_assignees;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_add_remove_assignees);
//supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
@ -65,7 +67,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 +92,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);
@ -234,14 +236,14 @@ public class AddRemoveAssigneesActivity extends AppCompatActivity {
private void updateIssueAssignees(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String loginUid, int issueIndex, List<String> issueAssigneesList) {
UpdateIssueAssignee updateAssigneeJson = new UpdateIssueAssignee(issueAssigneesList);
UpdateIssueAssignees updateAssigneeJson = new UpdateIssueAssignees(issueAssigneesList);
Call<JsonElement> call3;
call3 = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.patchIssueAssignee(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, updateAssigneeJson);
.patchIssueAssignees(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, updateAssigneeJson);
call3.enqueue(new Callback<JsonElement>() {

View File

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
@ -9,7 +8,6 @@ import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
@ -27,7 +25,7 @@ import java.util.List;
* Author M M Arif
*/
public class AddRemoveLabelsActivity extends AppCompatActivity {
public class AddRemoveLabelsActivity extends BaseActivity {
private ArrayList<MultiSelectModel> listOfLabels = new ArrayList<>();
private ArrayList<Integer> issueLabelIds = new ArrayList<>();
@ -36,10 +34,14 @@ public class AddRemoveLabelsActivity extends AppCompatActivity {
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_add_remove_labels;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_add_remove_labels);
//supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
@ -62,7 +64,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 +89,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 +251,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

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
@ -35,7 +34,7 @@ import java.util.Objects;
* Author M M Arif
*/
public class AdminGetUsersActivity extends AppCompatActivity implements AdminUsersBottomSheetFragment.BottomSheetListener {
public class AdminGetUsersActivity extends BaseActivity implements AdminUsersBottomSheetFragment.BottomSheetListener {
private View.OnClickListener onClickListener;
final Context ctx = this;
@ -45,10 +44,14 @@ public class AdminGetUsersActivity extends AppCompatActivity implements AdminUse
private Boolean searchFilter = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_admin_get_users;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_admin_get_users);
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");

View File

@ -0,0 +1,69 @@
package org.mian.gitnex.activities;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.FontsOverride;
import org.mian.gitnex.util.TinyDB;
/**
* Author M M Arif
*/
public abstract class BaseActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
if(tinyDb.getInt("themeId") == 1) {
setTheme(R.style.AppThemeLight);
}
else {
setTheme(R.style.AppTheme);
}
super.onCreate(savedInstanceState);
setContentView(getLayoutResourceId());
if(tinyDb.getInt("customFontId") == 0) {
FontsOverride.setDefaultFont(this, "DEFAULT", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "fonts/roboto.ttf");
}
else if (tinyDb.getInt("customFontId") == 1) {
FontsOverride.setDefaultFont(this, "DEFAULT", "fonts/manroperegular.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "fonts/manroperegular.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "fonts/manroperegular.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "fonts/manroperegular.ttf");
}
else if (tinyDb.getInt("customFontId") == 2) {
FontsOverride.setDefaultFont(this, "DEFAULT", "fonts/sourcecodeproregular.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "fonts/sourcecodeproregular.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "fonts/sourcecodeproregular.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "fonts/sourcecodeproregular.ttf");
}
else {
FontsOverride.setDefaultFont(this, "DEFAULT", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "fonts/roboto.ttf");
}
}
protected abstract int getLayoutResourceId();
}

View File

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@ -45,7 +44,7 @@ import java.util.List;
* Author M M Arif
*/
public class CreateIssueActivity extends AppCompatActivity implements View.OnClickListener {
public class CreateIssueActivity extends BaseActivity implements View.OnClickListener {
private View.OnClickListener onClickListener;
MultiSelectDialog multiSelectDialog;
@ -68,15 +67,20 @@ public class CreateIssueActivity extends AppCompatActivity implements View.OnCli
private ArrayAdapter<Mention> defaultMentionAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_create_issue;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_issue);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String loginFullName = tinyDb.getString("userFullname");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -109,7 +113,7 @@ public class CreateIssueActivity extends AppCompatActivity implements View.OnCli
getMilestones(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
getLabels(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
getCollaborators(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
getCollaborators(instanceUrl, instanceToken, repoOwner, repoName, loginUid, loginFullName);
disableProcessButton();
@ -217,7 +221,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 +252,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 +265,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);
@ -323,10 +327,11 @@ public class CreateIssueActivity extends AppCompatActivity implements View.OnCli
private void getMilestones(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
String msState = "open";
Call<List<Milestones>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getMilestones(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
.getMilestones(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, msState);
call.enqueue(new Callback<List<Milestones>>() {
@ -338,13 +343,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()
@ -375,13 +380,15 @@ public class CreateIssueActivity extends AppCompatActivity implements View.OnCli
}
private void getCollaborators(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
private void getCollaborators(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid, String loginFullName) {
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
listOfAssignees.add(new MultiSelectModel(-1, loginFullName));
call.enqueue(new Callback<List<Collaborators>>() {
@Override
@ -448,7 +455,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

@ -2,7 +2,6 @@ package org.mian.gitnex.activities;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import retrofit2.Call;
import retrofit2.Callback;
@ -28,12 +27,13 @@ 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
*/
public class CreateLabelActivity extends AppCompatActivity {
public class CreateLabelActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private TextView colorPicker;
@ -42,9 +42,13 @@ public class CreateLabelActivity extends AppCompatActivity {
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_create_label;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_label);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
@ -55,9 +59,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 +96,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 +246,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 +300,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 +373,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 +386,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

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
@ -26,7 +25,7 @@ import org.mian.gitnex.util.TinyDB;
* Author M M Arif
*/
public class CreateNewUserActivity extends AppCompatActivity {
public class CreateNewUserActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private EditText fullName;
@ -37,10 +36,14 @@ public class CreateNewUserActivity extends AppCompatActivity {
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_create_new_user;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_new_user);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
@ -127,7 +130,7 @@ public class CreateNewUserActivity extends AppCompatActivity {
Call<UserInfo> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewUser(instanceToken, createUser);

View File

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
@ -33,7 +32,7 @@ import java.util.List;
* Author M M Arif
*/
public class CreateReleaseActivity extends AppCompatActivity {
public class CreateReleaseActivity extends BaseActivity {
private View.OnClickListener onClickListener;
public ImageView closeActivity;
@ -49,10 +48,14 @@ public class CreateReleaseActivity extends AppCompatActivity {
List<Branches> branchesList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_create_release;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_release);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
@ -164,7 +167,7 @@ public class CreateReleaseActivity extends AppCompatActivity {
Call<Releases> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewRelease(token, repoOwner, repoName, createReleaseJson);
@ -224,7 +227,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

@ -2,7 +2,6 @@ package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
@ -30,7 +29,7 @@ import android.util.Log;
* Author M M Arif
*/
public class CreateTeamByOrgActivity extends AppCompatActivity implements View.OnClickListener {
public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClickListener {
final Context ctx = CreateTeamByOrgActivity.this;
private View.OnClickListener onClickListener;
@ -44,6 +43,11 @@ public class CreateTeamByOrgActivity extends AppCompatActivity implements View.O
private String[] permissionList = {"Read", "Write", "Admin"};
public int permissionSelectedChoice = -1;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_team_by_org;
}
private String[] accessControlsList = new String[] {
"Code",
"Issues",
@ -67,9 +71,8 @@ public class CreateTeamByOrgActivity extends AppCompatActivity implements View.O
};
@Override
protected void onCreate(Bundle savedInstanceState) {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_team_by_org);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
@ -89,7 +92,7 @@ public class CreateTeamByOrgActivity extends AppCompatActivity implements View.O
@Override
public void onClick(View view) {
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx, R.style.confirmDialog);
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx);
pBuilder.setTitle(R.string.newTeamPermission);
if(permissionSelectedChoice != -1) {
@ -141,7 +144,7 @@ public class CreateTeamByOrgActivity extends AppCompatActivity implements View.O
teamAccessControlsArray.setText("");
pushAccessList = Arrays.asList(accessControlsList);
AlertDialog.Builder aDialogBuilder = new AlertDialog.Builder(ctx, R.style.confirmDialog);
AlertDialog.Builder aDialogBuilder = new AlertDialog.Builder(ctx);
aDialogBuilder.setMultiChoiceItems(accessControlsList, selectedAccessControlsTrueFalse, new DialogInterface.OnMultiChoiceClickListener() {
@ -308,7 +311,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,35 +1,58 @@
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
*/
public class CreditsActivity extends AppCompatActivity {
public class CreditsActivity extends BaseActivity {
private View.OnClickListener onClickListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_credits;
}
@Override
public void onCreate(Bundle savedInstanceState) {
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

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@ -45,7 +44,7 @@ import java.util.List;
* Author M M Arif
*/
public class EditIssueActivity extends AppCompatActivity implements View.OnClickListener {
public class EditIssueActivity extends BaseActivity implements View.OnClickListener {
final Context ctx = this;
private View.OnClickListener onClickListener;
@ -56,14 +55,20 @@ public class EditIssueActivity extends AppCompatActivity implements View.OnClick
private Button editIssueButton;
private Spinner editIssueMilestoneSpinner;
private String msState = "open";
List<Milestones> milestonesList = new ArrayList<>();
private ArrayAdapter<Mention> defaultMentionAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_edit_issue;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_issue);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
@ -98,7 +103,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();
@ -120,7 +131,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);
@ -151,7 +162,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());
}
});
@ -227,7 +238,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);
@ -238,7 +249,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();
@ -305,7 +322,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);
@ -329,9 +346,9 @@ 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);
.getMilestones(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, msState);
final int finalMsId = msId;

View File

@ -0,0 +1,219 @@
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.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 BaseActivity {
private View.OnClickListener onClickListener;
private TextView toolbar_title;
private RecyclerView mRecyclerView;
private ProgressBar mProgressBar;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_file_diff;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
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);
if(appUtil.imageExtension(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,393 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.BitmapFactory;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.text.method.ScrollingMovementMethod;
import android.util.Base64;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.util.FitPolicy;
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.fragments.BottomSheetFileViewerFragment;
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.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class FileViewActivity extends BaseActivity implements BottomSheetFileViewerFragment.BottomSheetListener {
private View.OnClickListener onClickListener;
private TextView singleFileContents;
private LinearLayout singleFileContentsFrame;
private HighlightJsView singleCodeContents;
private PhotoView imageView;
final Context ctx = this;
private ProgressBar mProgressBar;
private byte[] imageData;
private PDFView pdfView;
private LinearLayout pdfViewFrame;
private byte[] decodedPdf;
private Boolean pdfNightMode;
private static final int PERMISSION_REQUEST_CODE = 1;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_file_view;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
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);
mProgressBar = findViewById(R.id.progress_bar);
pdfView = findViewById(R.id.pdfView);
pdfViewFrame = findViewById(R.id.pdfViewFrame);
singleFileContentsFrame = findViewById(R.id.singleFileContentsFrame);
String singleFileName = getIntent().getStringExtra("singleFileName");
TextView toolbar_title = findViewById(R.id.toolbar_title);
toolbar_title.setMovementMethod(new ScrollingMovementMethod());
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
tinyDb.putString("downloadFileContents", "");
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) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
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);
// download file meta
tinyDb.putString("downloadFileName", filename);
tinyDb.putString("downloadFileContents", response.body().getContent());
if(appUtil.imageExtension(fileExtension)) { // file is image
singleFileContentsFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.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);
singleFileContentsFrame.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.VISIBLE);
singleCodeContents.setTheme(Theme.GRUVBOX_DARK);
singleCodeContents.setShowLineNumbers(true);
singleCodeContents.setSource(appUtil.decodeBase64(response.body().getContent()));
}
else if (appUtil.pdfExtension(fileExtension)) { // file is pdf
imageView.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.VISIBLE);
pdfNightMode = tinyDb.getBoolean("enablePdfMode");
decodedPdf = Base64.decode(response.body().getContent(), Base64.DEFAULT);
pdfView.fromBytes(decodedPdf)
.enableSwipe(true)
.swipeHorizontal(false)
.enableDoubletap(true)
.defaultPage(0)
.enableAnnotationRendering(false)
.password(null)
.scrollHandle(null)
.enableAntialiasing(true)
.spacing(0)
.autoSpacing(true)
.pageFitPolicy(FitPolicy.WIDTH)
.fitEachPage(true)
.pageSnap(false)
.pageFling(true)
.nightMode(pdfNightMode)
.load();
}
else if (appUtil.excludeFilesInFileViewerExtension(fileExtension)) { // files need to be excluded
imageView.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setText(getResources().getString(R.string.excludeFilesInFileviewer));
singleFileContents.setGravity(Gravity.CENTER);
singleFileContents.setTypeface(null, Typeface.BOLD);
}
else { // file type not known - plain text view
imageView.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleFileContentsFrame.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());
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
finish();
return true;
case R.id.genericMenu:
BottomSheetFileViewerFragment bottomSheet = new BottomSheetFileViewerFragment();
bottomSheet.show(getSupportFragmentManager(), "fileViewerBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onButtonClicked(String text) {
switch (text) {
case "downloadFile":
if (Build.VERSION.SDK_INT >= 23)
{
if (checkPermission())
{
requestFileDownload();
}
else {
requestPermission();
}
}
else
{
requestFileDownload();
}
break;
}
}
private void requestFileDownload() {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
if(!tinyDb.getString("downloadFileContents").isEmpty()) {
File outputFileName = new File(tinyDb.getString("downloadFileName"));
final File downloadFilePath = new File(Environment.getExternalStorageDirectory().getPath() + "/Download/" + outputFileName.getName());
byte[] pdfAsBytes = Base64.decode(tinyDb.getString("downloadFileContents"), 0);
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(downloadFilePath, false);
Objects.requireNonNull(fileOutputStream).write(pdfAsBytes);
fileOutputStream.flush();
fileOutputStream.close();
Toasty.info(getApplicationContext(), getString(R.string.downloadFileSaved));
}
catch (IOException e) {
Log.e("errorFileDownloading", Objects.requireNonNull(e.getMessage()));
}
}
else {
Toasty.error(getApplicationContext(), getString(R.string.waitLoadingDownloadFile));
}
}
private boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
return result == PackageManager.PERMISSION_GRANTED;
}
private void requestPermission() {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.i("PermissionsCheck", "Permission Granted");
}
else {
Log.e("PermissionsCheck", "Permission Denied");
}
break;
}
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
getIntent().removeExtra("singleFileName");
finish();
}
};
}
}

View File

@ -2,7 +2,6 @@ package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
@ -10,26 +9,34 @@ import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import okhttp3.OkHttpClient;
import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin;
import io.noties.markwon.core.MarkwonTheme;
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tasklist.TaskListPlugin;
import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.AsyncDrawable;
import io.noties.markwon.image.DefaultMediaDecoder;
import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin;
import io.noties.markwon.image.SchemeHandler;
import io.noties.markwon.image.gif.GifMediaDecoder;
import io.noties.markwon.image.svg.SvgMediaDecoder;
import io.noties.markwon.linkify.LinkifyPlugin;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.Markwon;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import ru.noties.markwon.ext.tables.TablePlugin;
import ru.noties.markwon.ext.tasklist.TaskListPlugin;
import ru.noties.markwon.html.HtmlPlugin;
import ru.noties.markwon.image.ImagesPlugin;
import ru.noties.markwon.image.gif.GifPlugin;
import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.Html;
import android.text.Spanned;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
@ -63,6 +70,8 @@ import org.mian.gitnex.viewmodels.IssueCommentsViewModel;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@ -71,7 +80,7 @@ import java.util.Objects;
* Author M M Arif
*/
public class IssueDetailActivity extends AppCompatActivity {
public class IssueDetailActivity extends BaseActivity {
public ImageView closeActivity;
private IssueCommentsAdapter adapter;
@ -91,10 +100,14 @@ public class IssueDetailActivity extends AppCompatActivity {
private LinearLayout assigneesLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_issue_detail;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_issue_detail);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
@ -123,6 +136,8 @@ public class IssueDetailActivity extends AppCompatActivity {
assigneesLayout = findViewById(R.id.frameAssignees);
Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repoName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@ -143,12 +158,37 @@ 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);
}
});
Typeface myTypeface;
if(tinyDb.getInt("customFontId") == 0) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/roboto.ttf");
}
else if (tinyDb.getInt("customFontId") == 1) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/manroperegular.ttf");
}
else if (tinyDb.getInt("customFontId") == 2) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/sourcecodeproregular.ttf");
}
else {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/roboto.ttf");
}
toolbarTitle.setTypeface(myTypeface);
toolbarTitle.setText(repoName);
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
fetchDataAsync(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
@ -197,7 +237,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
@ -215,7 +255,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);
}
});
@ -255,7 +295,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);
@ -269,7 +309,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);
@ -286,22 +326,60 @@ public class IssueDetailActivity extends AppCompatActivity {
final Markwon markwon = Markwon.builder(Objects.requireNonNull(getApplicationContext()))
.usePlugin(CorePlugin.create())
.usePlugin(OkHttpImagesPlugin.create(new OkHttpClient()))
.usePlugin(ImagesPlugin.createWithAssets(getApplicationContext()))
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
@Override
public void configureImages(@NonNull ImagesPlugin plugin) {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = getApplicationContext().getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
getApplicationContext().getPackageName());
final Drawable drawable = getApplicationContext().getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
@Nullable
@Override
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
return null;
}
});
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(getApplicationContext().getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(getApplicationContext().getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder
.codeTextColor(tinyDb.getInt("codeBlockColor"))
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(getApplicationContext().getResources().getColor(R.color.lightBlue));
.linkColor(getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(getApplicationContext()))
.usePlugin(TaskListPlugin.create(getApplicationContext()))
.usePlugin(HtmlPlugin.create())
.usePlugin(GifPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
TinyDB tinyDb = new TinyDB(getApplicationContext());
@ -310,11 +388,12 @@ public class IssueDetailActivity extends AppCompatActivity {
tinyDb.putString("issueState", singleIssue.getState());
tinyDb.putString("issueTitle", singleIssue.getTitle());
Picasso.get().load(singleIssue.getUser().getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(assigneeAvatar);
issueTitle.setText(getString(R.string.issueTitleWithId, singleIssue.getNumber(), singleIssue.getTitle()));
Picasso.get().load(singleIssue.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar);
String issueNumber_ = "<font color='" + getApplicationContext().getResources().getColor(R.color.lightGray) + "'>" + getApplicationContext().getResources().getString(R.string.hash) + singleIssue.getNumber() + "</font>";
issueTitle.setText(Html.fromHtml(issueNumber_ + " " + singleIssue.getTitle()));
String cleanIssueDescription = singleIssue.getBody().trim();
final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueDescription));
issueDescription.setText(UserMentions.UserMentionsFunc(getApplicationContext(), bodyWithMD, cleanIssueDescription));
Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueDescription));
markwon.setParsedMarkdown(issueDescription, UserMentions.UserMentionsFunc(getApplicationContext(), bodyWithMD, cleanIssueDescription));
RelativeLayout.LayoutParams paramsDesc = (RelativeLayout.LayoutParams)issueDescription.getLayoutParams();
@ -327,7 +406,7 @@ public class IssueDetailActivity extends AppCompatActivity {
ImageView assigneesView = new ImageView(getApplicationContext());
Picasso.get().load(singleIssue.getAssignees().get(i).getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(80, 80).centerCrop().into(assigneesView);
Picasso.get().load(singleIssue.getAssignees().get(i).getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(100, 100).centerCrop().into(assigneesView);
assigneesLayout.addView(assigneesView);
assigneesView.setLayoutParams(params1);
@ -431,7 +510,7 @@ public class IssueDetailActivity extends AppCompatActivity {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(singleIssue.getCreated_at());
issueCreatedTime.setText(getString(R.string.createdTime, createdTime));
issueCreatedTime.setText(createdTime);
issueCreatedTime.setVisibility(View.VISIBLE);
issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(singleIssue.getCreated_at()), getApplicationContext()));
break;
@ -439,14 +518,14 @@ public class IssueDetailActivity extends AppCompatActivity {
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(singleIssue.getCreated_at());
issueCreatedTime.setText(getString(R.string.createdTime, createdTime));
issueCreatedTime.setText(createdTime);
issueCreatedTime.setVisibility(View.VISIBLE);
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(singleIssue.getCreated_at());
issueCreatedTime.setText(getString(R.string.createdTime, createdTime));
issueCreatedTime.setText(createdTime);
issueCreatedTime.setVisibility(View.VISIBLE);
break;
}

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 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.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import okhttp3.Credentials;
import okhttp3.Headers;
import retrofit2.Call;
import retrofit2.Callback;
@ -37,31 +44,42 @@ import retrofit2.Callback;
* Author M M Arif
*/
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
public class LoginActivity extends BaseActivity 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) {
protected int getLayoutResourceId(){
return R.layout.activity_login;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
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 +112,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 +146,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 +171,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,122 +199,350 @@ 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;
}
if(protocol.toLowerCase().equals("https")) {
instanceUrl = "https://" + instanceHost + "/api/v1/";
}
else {
instanceUrl = "http://" + instanceHost + "/api/v1/";
}
tinyDb.putString("instanceUrlRaw", instanceHost);
tinyDb.putString("loginUid", loginUid);
tinyDb.putString("instanceUrl", instanceUrl);
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.parseInt(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);
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);
final String credential = Credentials.basic(loginUid, loginPass, StandardCharsets.UTF_8);
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);
}
@ -286,7 +554,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()) {
@ -296,29 +565,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);
}
@ -328,7 +614,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) {
@ -341,6 +627,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));
@ -353,10 +640,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);
}
@ -383,20 +670,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);
}
@ -407,7 +694,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);
}
});
@ -415,21 +702,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

@ -5,10 +5,13 @@ import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import com.google.android.material.navigation.NavigationView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
@ -21,6 +24,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 +33,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;
@ -43,17 +48,25 @@ import retrofit2.Callback;
* Author M M Arif
*/
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener {
private DrawerLayout drawer;
private TextView userFullName;
private TextView userEmail;
private ImageView userAvatar;
private TextView toolbarTitle;
final Context ctx = this;
private Typeface myTypeface;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_main;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("noConnection", false);
//userAvatar = findViewById(R.id.userAvatar);
@ -84,17 +97,62 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(!tinyDb.getBoolean("loggedInMode")) {
logout();
return;
}
androidx.appcompat.widget.Toolbar toolbar = findViewById(R.id.toolbar);
Toolbar toolbar = findViewById(R.id.toolbar);
toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
if(tinyDb.getInt("customFontId") == 0) {
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/roboto.ttf");
}
else if (tinyDb.getInt("customFontId") == 1) {
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/manroperegular.ttf");
}
else if (tinyDb.getInt("customFontId") == 2) {
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/sourcecodeproregular.ttf");
}
else {
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/roboto.ttf");
}
toolbarTitle.setTypeface(myTypeface);
setSupportActionBar(toolbar);
FragmentManager fm = getSupportFragmentManager();
Fragment fragmentById = fm.findFragmentById(R.id.fragment_container);
if (fragmentById instanceof SettingsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
}
else if (fragmentById instanceof MyRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
}
else if (fragmentById instanceof StarredRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
}
else if (fragmentById instanceof OrganizationsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
}
else if (fragmentById instanceof ExploreRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
}
else if (fragmentById instanceof ProfileFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
}
else if (fragmentById instanceof AboutFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout));
}
drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
@ -110,7 +168,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar,
R.string.navigation_drawer_open, R.string.navigation_drawer_close);
toggle.getDrawerArrowDrawable().setColor(getResources().getColor(R.color.white));
toggle.getDrawerArrowDrawable().setColor(getResources().getColor(R.color.darkGreen));
drawer.addDrawerListener(toggle);
drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
@ -123,41 +181,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(100, 0)).resize(180, 180).centerCrop().into(userAvatar);
}
} else {
displayUserInfo(instanceUrl, instanceToken, loginUid);
if(tinyDb.getBoolean("noConnection")) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
tinyDb.putBoolean("noConnection", false);
}
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);
userEmail.setTypeface(myTypeface);
}
userFullName = hView.findViewById(R.id.userFullname);
if (!userFullNameNav.equals("")) {
userFullName.setText(userFullNameNav);
userFullName.setTypeface(myTypeface);
}
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
@ -175,31 +232,37 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
if(savedInstanceState == null) {
if(tinyDb.getInt("homeScreenId") == 0) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
}
else if(tinyDb.getInt("homeScreenId") == 1) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new StarredRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_starred_repos);
}
else if(tinyDb.getInt("homeScreenId") == 2) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations);
}
else if(tinyDb.getInt("homeScreenId") == 3) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories);
}
else if(tinyDb.getInt("homeScreenId") == 4) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
}
else {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
@ -217,6 +280,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
} else {
displayUserInfo(instanceUrl, instanceToken, loginUid);
giteaVersion(instanceUrl);
tinyDb.putBoolean("noConnection", false);
}
@ -244,22 +308,28 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
switch (menuItem.getItemId()) {
case R.id.nav_home:
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MyRepositoriesFragment()).commit();
break;
case R.id.nav_organizations:
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new OrganizationsFragment()).commit();
break;
case R.id.nav_profile:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ProfileFragment()).commit();
break;
case R.id.nav_repositories:
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new RepositoriesFragment()).commit();
break;
case R.id.nav_settings:
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new SettingsFragment()).commit();
break;
@ -268,6 +338,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
break;
case R.id.nav_about:
toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new AboutFragment()).commit();
break;
@ -275,9 +346,16 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
rateThisApp();
break;
case R.id.nav_starred_repos:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new StarredRepositoriesFragment()).commit();
break;
case R.id.nav_explore:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ExploreRepositoriesFragment()).commit();
break;
}
drawer.closeDrawer(GravityCompat.START);
@ -306,12 +384,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, @NonNull 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));
@ -330,13 +444,16 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
if (response.code() == 200) {
assert userDetails != null;
if(userDetails.getIs_admin() != null) {
tinyDb.putBoolean("userIsAdmin", userDetails.getIs_admin());
}
tinyDb.putString("userLogin", userDetails.getLogin());
tinyDb.putInt("userId", userDetails.getId());
if(!userDetails.getFullname().equals("")) {
tinyDb.putString("userFullname", userDetails.getFullname());
}
else {
tinyDb.putString("userFullname", "...");
tinyDb.putString("userFullname", userDetails.getLogin());
}
tinyDb.putString("userEmail", userDetails.getEmail());
@ -351,9 +468,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(100, 0)).resize(180, 180).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,261 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
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 BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
final Context ctx = this;
private SocialAutoCompleteTextView mergePR;
private ArrayAdapter<Mention> defaultMentionAdapter;
private Button mergeButton;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_merge_pull_request;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
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

@ -0,0 +1,338 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
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.models.Branches;
import org.mian.gitnex.models.NewFile;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class NewFileActivity extends BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
private Button newFileCreate;
private EditText newFileName;
private EditText newFileContent;
private EditText newFileBranchName;
private EditText newFileCommitMessage;
private Spinner newFileBranchesSpinner;
final Context ctx = this;
List<Branches> branchesList = new ArrayList<>();
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_file;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
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");
closeActivity = findViewById(R.id.close);
newFileName = findViewById(R.id.newFileName);
newFileContent = findViewById(R.id.newFileContent);
newFileBranchName = findViewById(R.id.newFileBranchName);
newFileCommitMessage = findViewById(R.id.newFileCommitMessage);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
newFileCreate = findViewById(R.id.newFileCreate);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
newFileBranchesSpinner = findViewById(R.id.newFileBranchesSpinner);
newFileBranchesSpinner.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
getBranches(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
newFileBranchesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
public void onItemSelected(AdapterView<?> arg0,
View arg1, int arg2, long arg3)
{
Branches bModelValue = (Branches) newFileBranchesSpinner.getSelectedItem();
Log.i("bModelSelected", bModelValue.toString());
if(bModelValue.toString().equals("No branch")) {
newFileBranchName.setEnabled(true);
}
else {
newFileBranchName.setEnabled(false);
newFileBranchName.setText("");
}
}
public void onNothingSelected(AdapterView<?> arg0) {}
});
disableProcessButton();
if(!connToInternet) {
newFileCreate.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
newFileCreate.setBackground(shape);
} else {
newFileCreate.setOnClickListener(createFileListener);
}
}
private View.OnClickListener createFileListener = new View.OnClickListener() {
public void onClick(View v) {
processNewFile();
}
};
private void processNewFile() {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil();
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];
String newFileName_ = newFileName.getText().toString();
String newFileContent_ = newFileContent.getText().toString();
String newFileBranchName_ = newFileBranchName.getText().toString();
String newFileCommitMessage_ = newFileCommitMessage.getText().toString();
Branches currentBranch = (Branches) newFileBranchesSpinner.getSelectedItem();
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if(newFileName_.equals("") || newFileContent_.equals("") || newFileCommitMessage_.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.newFileRequiredFields));
return;
}
if(currentBranch.toString().equals("No branch")) {
if(newFileBranchName_.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.newFileRequiredFieldNewBranchName));
return;
}
else {
if(!appUtil.checkStringsWithDash(newFileBranchName_)) {
Toasty.info(getApplicationContext(), getString(R.string.newFileInvalidBranchName));
return;
}
}
}
if(appUtil.charactersLength(newFileCommitMessage_) > 255) {
Toasty.info(getApplicationContext(), getString(R.string.newFileCommitMessageError));
}
else {
disableProcessButton();
createNewFile(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, newFileName_, appUtil.encodeBase64(newFileContent_), newFileBranchName_, newFileCommitMessage_, currentBranch.toString());
}
}
private void createNewFile(final String instanceUrl, final String token, String repoOwner, String repoName, String fileName, String fileContent, String fileBranchName, String fileCommitMessage, String currentBranch) {
NewFile createNewFileJsonStr;
if(currentBranch.equals("No branch")) {
createNewFileJsonStr = new NewFile("", fileContent, fileCommitMessage, fileBranchName);
}
else {
createNewFileJsonStr = new NewFile(currentBranch, fileContent, fileCommitMessage, "");
}
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewFile(token, repoOwner, repoName, fileName, createNewFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 201) {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.newFileSuccessMessage));
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.apiNotFound));
}
else {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.orgCreatedError));
}
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void getBranches(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getBranches(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Branches>>() {
@Override
public void onResponse(@NonNull Call<List<Branches>> call, @NonNull retrofit2.Response<List<Branches>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Branches> branchesList_ = response.body();
branchesList.add(new Branches("No branch"));
assert branchesList_ != null;
if(branchesList_.size() > 0) {
for (int i = 0; i < branchesList_.size(); i++) {
Branches data = new Branches(
branchesList_.get(i).getName()
);
branchesList.add(data);
}
}
ArrayAdapter<Branches> adapter = new ArrayAdapter<>(getApplicationContext(),
R.layout.spinner_item, branchesList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
newFileBranchesSpinner.setAdapter(adapter);
enableProcessButton();
}
}
}
@Override
public void onFailure(@NonNull Call<List<Branches>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private void disableProcessButton() {
newFileCreate.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
newFileCreate.setBackground(shape);
}
private void enableProcessButton() {
newFileCreate.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
newFileCreate.setBackground(shape);
}
}

View File

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.app.DatePickerDialog;
@ -18,6 +17,7 @@ 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.VersionCheck;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.util.AppUtil;
@ -28,7 +28,7 @@ import java.util.Calendar;
* Author M M Arif
*/
public class NewMilestoneActivity extends AppCompatActivity implements View.OnClickListener {
public class NewMilestoneActivity extends BaseActivity implements View.OnClickListener {
private EditText milestoneDueDate;
private View.OnClickListener onClickListener;
@ -38,9 +38,13 @@ public class NewMilestoneActivity extends AppCompatActivity implements View.OnCl
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_new_milestone;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_milestone);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
@ -117,15 +121,16 @@ public class NewMilestoneActivity extends AppCompatActivity implements View.OnCl
}
}
if(newMilestoneDueDate.equals("")) {
String finalMilestoneDueDate = null;
if(!newMilestoneDueDate.isEmpty()) {
finalMilestoneDueDate = (AppUtil.customDateCombine(AppUtil.customDateFormat(newMilestoneDueDate)));
} else if (VersionCheck.compareVersion("1.10.0", tinyDb.getString("giteaVersion")) > 1) {
// if Gitea version is less than 1.10.0 DueDate is required
Toasty.info(getApplicationContext(), getString(R.string.milestoneDateEmpty));
return;
}
disableProcessButton();
String finalMilestoneDueDate = (AppUtil.customDateCombine(AppUtil.customDateFormat(newMilestoneDueDate)));
createNewMilestone(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, newMilestoneTitle, newMilestoneDescription, finalMilestoneDueDate);
}
@ -137,7 +142,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

@ -4,7 +4,6 @@ import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@ -25,7 +24,7 @@ import retrofit2.Callback;
* Author M M Arif
*/
public class NewOrganizationActivity extends AppCompatActivity {
public class NewOrganizationActivity extends BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
@ -36,9 +35,13 @@ public class NewOrganizationActivity extends AppCompatActivity {
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_new_organization;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_organization);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
@ -134,7 +137,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

@ -5,7 +5,6 @@ import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
@ -33,7 +32,7 @@ import retrofit2.Callback;
* Author M M Arif
*/
public class NewRepoActivity extends AppCompatActivity {
public class NewRepoActivity extends BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
@ -47,9 +46,13 @@ public class NewRepoActivity extends AppCompatActivity {
List<OrgOwner> orgsList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_new_repo;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_repo);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
@ -162,7 +165,7 @@ public class NewRepoActivity extends AppCompatActivity {
if(repoOwner.equals(loginUid)) {
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewUserRepository(token, createRepository);
@ -170,7 +173,7 @@ public class NewRepoActivity extends AppCompatActivity {
else {
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.createNewUserOrgRepository(token, repoOwner, createRepository);
@ -225,7 +228,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

@ -0,0 +1,35 @@
package org.mian.gitnex.activities;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import org.mian.gitnex.util.TinyDB;
/**
* Author M M Arif
*/
public class OpenRepoInBrowserActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TinyDB tinyDb = new TinyDB(getApplicationContext());
String instanceUrlWithProtocol = "https://" + tinyDb.getString("instanceUrlRaw");
if (!tinyDb.getString("instanceUrlWithProtocol").isEmpty()) {
instanceUrlWithProtocol = tinyDb.getString("instanceUrlWithProtocol");
}
String repoFullNameBrowser = getIntent().getStringExtra("repoFullNameBrowser");
Uri url = Uri.parse(instanceUrlWithProtocol + "/" + repoFullNameBrowser);
Intent i = new Intent(Intent.ACTION_VIEW, url);
startActivity(i);
finish();
}
}

View File

@ -2,17 +2,20 @@ package org.mian.gitnex.activities;
import com.google.android.material.tabs.TabLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.fragments.MembersByOrgFragment;
import org.mian.gitnex.fragments.OrgBottomSheetFragment;
@ -26,17 +29,23 @@ import java.util.Objects;
* Author M M Arif
*/
public class OrgDetailActivity extends AppCompatActivity implements OrgBottomSheetFragment.BottomSheetListener {
public class OrgDetailActivity extends BaseActivity implements OrgBottomSheetFragment.BottomSheetListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_org_detail;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_org_detail);
TinyDB tinyDb = new TinyDB(getApplicationContext());
String orgName = tinyDb.getString("orgName");
Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(orgName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@ -48,6 +57,44 @@ public class OrgDetailActivity extends AppCompatActivity implements OrgBottomShe
TabLayout tabLayout = findViewById(R.id.tabs);
Typeface myTypeface;
if(tinyDb.getInt("customFontId") == 0) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/roboto.ttf");
}
else if (tinyDb.getInt("customFontId") == 1) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/manroperegular.ttf");
}
else if (tinyDb.getInt("customFontId") == 2) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/sourcecodeproregular.ttf");
}
else {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/roboto.ttf");
}
toolbarTitle.setTypeface(myTypeface);
toolbarTitle.setText(orgName);
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = vg.getChildCount();
for (int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
int tabChildCount = vgTab.getChildCount();
for (int i = 0; i < tabChildCount; i++) {
View tabViewChild = vgTab.getChildAt(i);
if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(myTypeface);
}
}
}
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));

View File

@ -1,11 +1,9 @@
package org.mian.gitnex.activities;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
@ -17,12 +15,13 @@ import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.TeamMembersByOrgViewModel;
import java.util.List;
import java.util.Objects;
/**
* Author M M Arif
*/
public class OrgTeamMembersActivity extends AppCompatActivity {
public class OrgTeamMembersActivity extends BaseActivity {
private TextView noDataMembers;
private View.OnClickListener onClickListener;
@ -30,9 +29,13 @@ public class OrgTeamMembersActivity extends AppCompatActivity {
private GridView mGridView;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_org_team_members;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_org_team_members);
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
@ -47,7 +50,7 @@ public class OrgTeamMembersActivity extends AppCompatActivity {
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(getIntent().getStringExtra("teamTitle") != null && !getIntent().getStringExtra("teamTitle").equals("")) {
if(getIntent().getStringExtra("teamTitle") != null && !Objects.requireNonNull(getIntent().getStringExtra("teamTitle")).equals("")) {
toolbarTitle.setText(getIntent().getStringExtra("teamTitle"));
}
else {
@ -55,7 +58,7 @@ public class OrgTeamMembersActivity extends AppCompatActivity {
}
String teamId;
if(getIntent().getStringExtra("teamId") != null && !getIntent().getStringExtra("teamId").equals("")){
if(getIntent().getStringExtra("teamId") != null && !Objects.requireNonNull(getIntent().getStringExtra("teamId")).equals("")){
teamId = getIntent().getStringExtra("teamId");
}
else {
@ -63,17 +66,18 @@ public class OrgTeamMembersActivity extends AppCompatActivity {
}
getIntent().getStringExtra("teamId");
Log.i("teamId", getIntent().getStringExtra("teamId"));
//Log.i("teamId", getIntent().getStringExtra("teamId"));
assert teamId != null;
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), Integer.valueOf(teamId));
}
private void fetchDataAsync(String instanceUrl, String instanceToken, int teamId) {
TeamMembersByOrgViewModel teamMembersModel = ViewModelProviders.of(this).get(TeamMembersByOrgViewModel.class);
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

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
@ -30,7 +29,7 @@ import java.util.List;
* Author M M Arif
*/
public class ProfileEmailActivity extends AppCompatActivity {
public class ProfileEmailActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private EditText userEmail;
@ -38,9 +37,13 @@ public class ProfileEmailActivity extends AppCompatActivity {
private Button addEmailButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_profile_email;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile_email);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
@ -114,7 +117,7 @@ public class ProfileEmailActivity extends AppCompatActivity {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.addNewEmail(token, addEmailFunc);

View File

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@ -33,7 +32,7 @@ import java.util.List;
* Author M M Arif
*/
public class ReplyToIssueActivity extends AppCompatActivity {
public class ReplyToIssueActivity extends BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
@ -45,10 +44,14 @@ public class ReplyToIssueActivity extends AppCompatActivity {
private Button replyButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_reply_to_issue;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reply_to_issue);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
@ -83,6 +86,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 +121,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 +215,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 +229,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,8 +1,8 @@
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;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@ -10,7 +10,10 @@ import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import retrofit2.Call;
import retrofit2.Callback;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
@ -18,36 +21,45 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.mian.gitnex.R;
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;
import android.net.Uri;
/**
* Author M M Arif
*/
public class RepoDetailActivity extends AppCompatActivity implements RepoBottomSheetFragment.BottomSheetListener {
public class RepoDetailActivity extends BaseActivity implements RepoBottomSheetFragment.BottomSheetListener {
private TextView textViewBadge;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_repo_detail;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_repo_detail);
TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
@ -63,6 +75,8 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
AppUtil.setAppLocale(getResources(), appLocale);
Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repoName1);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@ -74,19 +88,66 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
TabLayout tabLayout = findViewById(R.id.tabs);
Typeface myTypeface;
if(tinyDb.getInt("customFontId") == 0) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/roboto.ttf");
}
else if (tinyDb.getInt("customFontId") == 1) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/manroperegular.ttf");
}
else if (tinyDb.getInt("customFontId") == 2) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/sourcecodeproregular.ttf");
}
else {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getApplicationContext()).getAssets(), "fonts/roboto.ttf");
}
toolbarTitle.setTypeface(myTypeface);
toolbarTitle.setText(repoName1);
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = vg.getChildCount();
for (int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
int tabChildCount = vgTab.getChildCount();
for (int i = 0; i < tabChildCount; i++) {
View tabViewChild = vgTab.getChildAt(i);
if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(myTypeface);
}
}
}
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
if(tinyDb.getBoolean("enableCounterIssueBadge")) {
View tabHeader = LayoutInflater.from(this).inflate(R.layout.badge, null);
@SuppressLint("InflateParams") View tabHeader = LayoutInflater.from(this).inflate(R.layout.badge, null);
textViewBadge = tabHeader.findViewById(R.id.counterBadge);
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(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
@ -107,7 +168,6 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
@ -153,6 +213,20 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
case "createRelease":
startActivity(new Intent(RepoDetailActivity.this, CreateReleaseActivity.class));
break;
case "openWebRepo":
TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
String instanceUrlWithProtocol = "https://" + tinyDb.getString("instanceUrlRaw");
if(!tinyDb.getString("instanceUrlWithProtocol").isEmpty()) {
instanceUrlWithProtocol = tinyDb.getString("instanceUrlWithProtocol");
}
Uri url = Uri.parse(instanceUrlWithProtocol + "/" + repoFullName);
Intent i = new Intent(Intent.ACTION_VIEW, url);
startActivity(i);
break;
case "newFile":
startActivity(new Intent(RepoDetailActivity.this, NewFileActivity.class));
break;
}
}
@ -160,7 +234,7 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
SectionsPagerAdapter(FragmentManager fm) {
super(fm);
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
@NonNull
@ -177,21 +251,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;
@ -199,7 +278,7 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
@Override
public int getCount() {
return 8;
return 10;
}
}
@ -207,7 +286,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);
@ -242,4 +321,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

@ -0,0 +1,98 @@
package org.mian.gitnex.activities;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoStargazersAdapter;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.RepoStargazersViewModel;
import java.util.List;
/**
* Author M M Arif
*/
public class RepoStargazersActivity extends BaseActivity {
private TextView noDataStargazers;
private View.OnClickListener onClickListener;
private RepoStargazersAdapter adapter;
private GridView mGridView;
private ProgressBar mProgressBar;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repo_stargazers;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
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");
ImageView closeActivity = findViewById(R.id.close);
TextView toolbarTitle = findViewById(R.id.toolbar_title);
noDataStargazers = findViewById(R.id.noDataStargazers);
mGridView = findViewById(R.id.gridView);
mProgressBar = findViewById(R.id.progress_bar);
String repoFullNameForStars = getIntent().getStringExtra("repoFullNameForStars");
String[] parts = repoFullNameForStars.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
toolbarTitle.setText(R.string.repoStargazersInMenu);
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String repoOwner, String repoName) {
RepoStargazersViewModel repoStargazersModel = new ViewModelProvider(this).get(RepoStargazersViewModel.class);
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);
if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter);
noDataStargazers.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mGridView.setAdapter(adapter);
noDataStargazers.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}

View File

@ -0,0 +1,98 @@
package org.mian.gitnex.activities;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoWatchersAdapter;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.RepoWatchersViewModel;
import java.util.List;
/**
* Author M M Arif
*/
public class RepoWatchersActivity extends BaseActivity {
private TextView noDataWatchers;
private View.OnClickListener onClickListener;
private RepoWatchersAdapter adapter;
private GridView mGridView;
private ProgressBar mProgressBar;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repo_watchers;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
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");
ImageView closeActivity = findViewById(R.id.close);
TextView toolbarTitle = findViewById(R.id.toolbar_title);
noDataWatchers = findViewById(R.id.noDataWatchers);
mGridView = findViewById(R.id.gridView);
mProgressBar = findViewById(R.id.progress_bar);
String repoFullNameForWatchers = getIntent().getStringExtra("repoFullNameForWatchers");
String[] parts = repoFullNameForWatchers.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
toolbarTitle.setText(R.string.repoWatchersInMenu);
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String repoOwner, String repoName) {
RepoWatchersViewModel repoWatchersModel = new ViewModelProvider(this).get(RepoWatchersViewModel.class);
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);
if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter);
noDataWatchers.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mGridView.setAdapter(adapter);
noDataWatchers.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}

View File

@ -1,28 +1,57 @@
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.view.View;
import android.widget.ImageView;
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
*/
public class SponsorsActivity extends AppCompatActivity {
public class SponsorsActivity extends BaseActivity {
private View.OnClickListener onClickListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
protected int getLayoutResourceId(){
return R.layout.activity_sponsors;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sponsors);
ImageView closeActivity = findViewById(R.id.close);
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

@ -98,7 +98,7 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
holder.userRole.setVisibility(View.GONE);
}
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(100, 0)).resize(140, 140).centerCrop().into(holder.userAvatar);
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
}
@Override

View File

@ -1,12 +1,13 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
@ -66,7 +67,9 @@ public class BranchesAdapter extends RecyclerView.Adapter<BranchesAdapter.Branch
holder.branchCommitAuthor.setText(mCtx.getResources().getString(R.string.commitAuthor, currentItem.getCommit().getAuthor().getUsername()));
}
holder.branchCommitHash.setText(mCtx.getResources().getString(R.string.commitHash, UrlHelper.cleanUrl(instanceUrl), currentItem.getCommit().getUrl()));
holder.branchCommitHash.setText(
Html.fromHtml("<a href='" + currentItem.getCommit().getUrl() + "'>" + mCtx.getResources().getString(R.string.commitLinkBranchesTab) + "</a> "));
holder.branchCommitHash.setMovementMethod(LinkMovementMethod.getInstance());
}

View File

@ -3,22 +3,22 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
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.RelativeLayout;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import com.vdurmont.emoji.EmojiParser;
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.helpers.UserMentions;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.util.TinyDB;
import org.ocpsoft.prettytime.PrettyTime;
@ -27,22 +27,8 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import okhttp3.OkHttpClient;
import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.Markwon;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import ru.noties.markwon.ext.tables.TablePlugin;
import ru.noties.markwon.ext.tables.TableTheme;
import ru.noties.markwon.ext.tasklist.TaskListPlugin;
import ru.noties.markwon.html.HtmlPlugin;
import ru.noties.markwon.image.ImagesPlugin;
import ru.noties.markwon.image.gif.GifPlugin;
import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin;
/**
* Author M M Arif
@ -122,11 +108,9 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
private TextView issueNumber;
private ImageView issueAssigneeAvatar;
private TextView issueTitle;
private TextView issueDescription;
//private ImageView issueState;
private TextView issueCreatedTime;
private TextView issueCommentsCount;
private ImageView issueType;
private RelativeLayout relativeLayoutFrame;
IssuesHolder(View itemView) {
@ -135,11 +119,10 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
issueNumber = itemView.findViewById(R.id.issueNumber);
issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
issueTitle = itemView.findViewById(R.id.issueTitle);
issueDescription = itemView.findViewById(R.id.issueDescription);
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
//issueState = itemView.findViewById(R.id.issueStatus);
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
@ -153,11 +136,12 @@ 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);
}
});
issueDescription.setOnClickListener(new View.OnClickListener() {
frameCommentsCount.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -169,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);
}
@ -183,25 +168,12 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
final Markwon markwon = Markwon.builder(Objects.requireNonNull(context))
.usePlugin(CorePlugin.create())
.usePlugin(OkHttpImagesPlugin.create(new OkHttpClient()))
.usePlugin(ImagesPlugin.createWithAssets(context))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder
.codeTextColor(tinyDb.getInt("codeBlockColor"))
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(context.getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(context))
.usePlugin(TaskListPlugin.create(context))
.usePlugin(HtmlPlugin.create())
.usePlugin(GifPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.build();
/*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));
@ -210,41 +182,17 @@ public class ClosedIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
if (issuesModel.getUser().getAvatar_url() != null) {
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(issueAssigneeAvatar);
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar);
} else {
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(issueAssigneeAvatar);
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()));
issueTitle.setText(context.getResources().getString(R.string.hash) + issuesModel.getNumber() + " " + issuesModel.getTitle());
issueNumber.setText(String.valueOf(issuesModel.getNumber()));
issueCommentsCount.setText(String.valueOf(issuesModel.getComments()));
if (!issuesModel.getBody().equals("")) {
String cleanIssueDescription = issuesModel.getBody().trim();
issueDescription.setVisibility(View.VISIBLE);
final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueDescription));
issueDescription.setText(UserMentions.UserMentionsFunc(context, bodyWithMD, cleanIssueDescription));
}
else {
issueDescription.setText("");
issueDescription.setVisibility(View.GONE);
}
/*if (issuesModel.getState().equals("open")) {
issueState.setImageResource(R.drawable.ic_issue_open);
issueState.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueStatusTextOpen), context));
} else {
issueState.setImageResource(R.drawable.ic_issue_closed);
issueState.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueStatusTextClosed), context));
}*/
switch (timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));

View File

@ -77,7 +77,7 @@ public class CollaboratorsAdapter extends BaseAdapter {
private void initData(ViewHolder viewHolder, int position) {
Collaborators currentItem = collaboratorsList.get(position);
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(viewHolder.collaboratorAvatar);
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.collaboratorAvatar);
if(!currentItem.getFull_name().equals("")) {
viewHolder.collaboratorName.setText(currentItem.getFull_name());

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,217 @@
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;
import java.util.Objects;
/**
* 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 };
Objects.requireNonNull(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

@ -3,7 +3,9 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
@ -14,8 +16,8 @@ import com.squareup.picasso.Picasso;
import com.vdurmont.emoji.EmojiParser;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.helpers.UserMentions;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.UserMentions;
import org.mian.gitnex.models.IssueComments;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.util.TinyDB;
@ -24,26 +26,32 @@ import org.ocpsoft.prettytime.PrettyTime;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
import okhttp3.OkHttpClient;
import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.Markwon;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import ru.noties.markwon.ext.tables.TablePlugin;
import ru.noties.markwon.ext.tables.TableTheme;
import ru.noties.markwon.ext.tasklist.TaskListPlugin;
import ru.noties.markwon.html.HtmlPlugin;
import ru.noties.markwon.image.ImagesPlugin;
import ru.noties.markwon.image.gif.GifPlugin;
import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin;
import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin;
import io.noties.markwon.core.MarkwonTheme;
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tasklist.TaskListPlugin;
import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.AsyncDrawable;
import io.noties.markwon.image.DefaultMediaDecoder;
import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin;
import io.noties.markwon.image.SchemeHandler;
import io.noties.markwon.image.gif.GifMediaDecoder;
import io.noties.markwon.image.svg.SvgMediaDecoder;
import io.noties.markwon.linkify.LinkifyPlugin;
/**
* Author M M Arif
@ -82,9 +90,9 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
public void onClick(View v) {
final Context context = v.getContext();
Context context_ = new ContextThemeWrapper(context, R.style.popupMenuStyle);
//Context context_ = new ContextThemeWrapper(context, R.style.popupMenuStyle);
PopupMenu popupMenu = new PopupMenu(context_, v);
PopupMenu popupMenu = new PopupMenu(context, v);
popupMenu.inflate(R.menu.issue_comment_menu);
Object menuHelper;
@ -171,34 +179,72 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
}
if (currentItem.getUser().getAvatar_url() != null) {
Picasso.get().load(currentItem.getUser().getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(holder.issueCommenterAvatar);
Picasso.get().load(currentItem.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.issueCommenterAvatar);
} else {
Picasso.get().load(currentItem.getUser().getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(holder.issueCommenterAvatar);
Picasso.get().load(currentItem.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.issueCommenterAvatar);
}
String cleanIssueComments = currentItem.getBody().trim();
final Markwon markwon = Markwon.builder(Objects.requireNonNull(mCtx))
.usePlugin(CorePlugin.create())
.usePlugin(OkHttpImagesPlugin.create(new OkHttpClient()))
.usePlugin(ImagesPlugin.create(mCtx))
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
@Override
public void configureImages(@NonNull ImagesPlugin plugin) {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = mCtx.getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
mCtx.getPackageName());
final Drawable drawable = mCtx.getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
@Nullable
@Override
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
return null;
}
});
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder
.codeTextColor(tinyDb.getInt("codeBlockColor"))
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"));
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(mCtx.getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(mCtx))
.usePlugin(TaskListPlugin.create(mCtx))
.usePlugin(HtmlPlugin.create())
.usePlugin(GifPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueComments));
holder.issueComment.setText(UserMentions.UserMentionsFunc(mCtx, bodyWithMD, cleanIssueComments));
Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueComments));
markwon.setParsedMarkdown(holder.issueComment, UserMentions.UserMentionsFunc(mCtx, bodyWithMD, cleanIssueComments));
String edited;

View File

@ -3,22 +3,22 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
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.RelativeLayout;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import com.vdurmont.emoji.EmojiParser;
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.helpers.UserMentions;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.util.TinyDB;
import org.ocpsoft.prettytime.PrettyTime;
@ -27,22 +27,8 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import okhttp3.OkHttpClient;
import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.Markwon;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import ru.noties.markwon.ext.tables.TablePlugin;
import ru.noties.markwon.ext.tables.TableTheme;
import ru.noties.markwon.ext.tasklist.TaskListPlugin;
import ru.noties.markwon.html.HtmlPlugin;
import ru.noties.markwon.image.ImagesPlugin;
import ru.noties.markwon.image.gif.GifPlugin;
import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin;
/**
* Author M M Arif
@ -122,11 +108,9 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
private TextView issueNumber;
private ImageView issueAssigneeAvatar;
private TextView issueTitle;
private TextView issueDescription;
//private ImageView issueState;
private TextView issueCreatedTime;
private TextView issueCommentsCount;
private ImageView issueType;
private RelativeLayout relativeLayoutFrame;
IssuesHolder(View itemView) {
@ -135,11 +119,10 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
issueNumber = itemView.findViewById(R.id.issueNumber);
issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
issueTitle = itemView.findViewById(R.id.issueTitle);
issueDescription = itemView.findViewById(R.id.issueDescription);
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
//issueState = itemView.findViewById(R.id.issueStatus);
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
@ -153,11 +136,12 @@ 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);
}
});
issueDescription.setOnClickListener(new View.OnClickListener() {
frameCommentsCount.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -169,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);
}
@ -183,25 +168,12 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
final Markwon markwon = Markwon.builder(Objects.requireNonNull(context))
.usePlugin(CorePlugin.create())
.usePlugin(OkHttpImagesPlugin.create(new OkHttpClient()))
.usePlugin(ImagesPlugin.createWithAssets(context))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder
.codeTextColor(tinyDb.getInt("codeBlockColor"))
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(context.getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(context))
.usePlugin(TaskListPlugin.create(context))
.usePlugin(HtmlPlugin.create())
.usePlugin(GifPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.build();
/*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));
@ -210,41 +182,17 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
}
if (issuesModel.getUser().getAvatar_url() != null) {
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(issueAssigneeAvatar);
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar);
} else {
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(issueAssigneeAvatar);
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()));
issueTitle.setText(context.getResources().getString(R.string.hash) + issuesModel.getNumber() + " " + issuesModel.getTitle());
issueNumber.setText(String.valueOf(issuesModel.getNumber()));
issueCommentsCount.setText(String.valueOf(issuesModel.getComments()));
if (!issuesModel.getBody().equals("")) {
String cleanIssueDescription = issuesModel.getBody().trim();
issueDescription.setVisibility(View.VISIBLE);
final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueDescription));
issueDescription.setText(UserMentions.UserMentionsFunc(context, bodyWithMD, cleanIssueDescription));
}
else {
issueDescription.setText("");
issueDescription.setVisibility(View.GONE);
}
/*if (issuesModel.getState().equals("open")) {
issueState.setImageResource(R.drawable.ic_issue_open);
issueState.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueStatusTextOpen), context));
} else {
issueState.setImageResource(R.drawable.ic_issue_closed);
issueState.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueStatusTextClosed), context));
}*/
switch (timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));

View File

@ -3,7 +3,6 @@ package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
@ -42,13 +41,12 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
private TextView labelId;
private TextView labelColor;
private ImageView labelsView;
private ImageView labelsOptionsMenu;
private LabelsViewHolder(View itemView) {
super(itemView);
labelsView = itemView.findViewById(R.id.labelsView);
labelsOptionsMenu = itemView.findViewById(R.id.labelsOptionsMenu);
ImageView labelsOptionsMenu = itemView.findViewById(R.id.labelsOptionsMenu);
labelTitle = itemView.findViewById(R.id.labelTitle);
labelId = itemView.findViewById(R.id.labelId);
labelColor = itemView.findViewById(R.id.labelColor);
@ -58,9 +56,9 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
public void onClick(View v) {
final Context context = v.getContext();
Context context_ = new ContextThemeWrapper(context, R.style.popupMenuStyle);
//Context context_ = new ContextThemeWrapper(context, R.style.popupMenuStyle);
PopupMenu popupMenu = new PopupMenu(context_, v);
PopupMenu popupMenu = new PopupMenu(context, v);
popupMenu.inflate(R.menu.labels_menu);
Object menuHelper;
@ -146,6 +144,7 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
//.useFont(Typeface.DEFAULT)
.bold()
.textColor(new ColorInverter().getContrastColor(color))
.fontSize(36)
.width(LabelWidthCalculator.customWidth(getMaxLabelLength()))

View File

@ -83,7 +83,7 @@ public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
private void initData(MembersByOrgAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = membersList.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(120, 120).centerCrop().into(viewHolder.memberAvatar);
if(!currentItem.getFullname().equals("")) {
viewHolder.memberName.setText(currentItem.getFullname());

View File

@ -3,12 +3,16 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Spanned;
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.ProgressBar;
import android.widget.TextView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.vdurmont.emoji.EmojiParser;
@ -21,25 +25,31 @@ import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import okhttp3.OkHttpClient;
import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.Markwon;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import ru.noties.markwon.ext.tables.TablePlugin;
import ru.noties.markwon.ext.tables.TableTheme;
import ru.noties.markwon.ext.tasklist.TaskListPlugin;
import ru.noties.markwon.html.HtmlPlugin;
import ru.noties.markwon.image.ImagesPlugin;
import ru.noties.markwon.image.gif.GifPlugin;
import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin;
import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin;
import io.noties.markwon.core.MarkwonTheme;
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tasklist.TaskListPlugin;
import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.AsyncDrawable;
import io.noties.markwon.image.DefaultMediaDecoder;
import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin;
import io.noties.markwon.image.SchemeHandler;
import io.noties.markwon.image.gif.GifMediaDecoder;
import io.noties.markwon.image.svg.SvgMediaDecoder;
import io.noties.markwon.linkify.LinkifyPlugin;
/**
* Author M M Arif
@ -59,6 +69,7 @@ public class MilestonesAdapter extends RecyclerView.Adapter<MilestonesAdapter.Mi
private TextView msClosedIssues;
private TextView msDueDate;
private ImageView msStatus;
private ProgressBar msProgress;
private MilestonesViewHolder(View itemView) {
super(itemView);
@ -69,8 +80,9 @@ public class MilestonesAdapter extends RecyclerView.Adapter<MilestonesAdapter.Mi
msOpenIssues = itemView.findViewById(R.id.milestoneIssuesOpen);
msClosedIssues = itemView.findViewById(R.id.milestoneIssuesClosed);
msDueDate = itemView.findViewById(R.id.milestoneDueDate);
msProgress = itemView.findViewById(R.id.milestoneProgress);
/*issueTitle.setOnClickListener(new View.OnClickListener() {
/*msTitle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -113,8 +125,45 @@ public class MilestonesAdapter extends RecyclerView.Adapter<MilestonesAdapter.Mi
final Markwon markwon = Markwon.builder(Objects.requireNonNull(mCtx))
.usePlugin(CorePlugin.create())
.usePlugin(OkHttpImagesPlugin.create(new OkHttpClient()))
.usePlugin(ImagesPlugin.createWithAssets(mCtx))
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
@Override
public void configureImages(@NonNull ImagesPlugin plugin) {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = mCtx.getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
mCtx.getPackageName());
final Drawable drawable = mCtx.getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
@Nullable
@Override
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
return null;
}
});
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
@ -127,11 +176,12 @@ public class MilestonesAdapter extends RecyclerView.Adapter<MilestonesAdapter.Mi
.usePlugin(TablePlugin.create(mCtx))
.usePlugin(TaskListPlugin.create(mCtx))
.usePlugin(HtmlPlugin.create())
.usePlugin(GifPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
holder.msTitle.setText(currentItem.getTitle());
Spanned msTitle = markwon.toMarkdown(currentItem.getTitle());
markwon.setParsedMarkdown(holder.msTitle, msTitle);
//holder.msStatus.setText(currentItem.getState());
if(currentItem.getState().equals("open")) {
@ -183,6 +233,24 @@ public class MilestonesAdapter extends RecyclerView.Adapter<MilestonesAdapter.Mi
holder.msClosedIssues.setText(String.valueOf(currentItem.getClosed_issues()));
holder.msClosedIssues.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.milestoneClosedIssues, currentItem.getClosed_issues()), mCtx));
if ((currentItem.getOpen_issues() + currentItem.getClosed_issues()) > 0) {
if (currentItem.getOpen_issues() == 0) {
holder.msProgress.setProgress(100);
holder.msProgress.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.milestoneCompletion, 100), mCtx));
}
else {
int msCompletion = 100 * currentItem.getClosed_issues() / (currentItem.getOpen_issues() + currentItem.getClosed_issues());
holder.msProgress.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.milestoneCompletion, msCompletion), mCtx));
holder.msProgress.setProgress(msCompletion);
}
}
else {
holder.msProgress.setProgress(0);
holder.msProgress.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.milestoneCompletion, 0), mCtx));
}
if(currentItem.getDue_on() != null) {
if (timeFormat.equals("normal") || timeFormat.equals("pretty")) {
@ -216,7 +284,7 @@ public class MilestonesAdapter extends RecyclerView.Adapter<MilestonesAdapter.Mi
}
else {
holder.msDueDate.setVisibility(View.INVISIBLE);
holder.msDueDate.setVisibility(View.GONE);
}
}

View File

@ -4,6 +4,7 @@ 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.Filter;
@ -12,13 +13,21 @@ import android.widget.ImageView;
import android.widget.TextView;
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.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
/**
@ -39,8 +48,9 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
private TextView fullNameMy;
private ImageView repoPrivatePublicMy;
private TextView repoStarsMy;
private TextView repoWatchersMy;
private TextView repoForksMy;
private TextView repoOpenIssuesCountMy;
private TextView repoType;
private MyReposViewHolder(View itemView) {
super(itemView);
@ -50,8 +60,10 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
fullNameMy = itemView.findViewById(R.id.repoFullNameMy);
repoPrivatePublicMy = itemView.findViewById(R.id.imageRepoTypeMy);
repoStarsMy = itemView.findViewById(R.id.repoStarsMy);
repoWatchersMy = itemView.findViewById(R.id.repoWatchersMy);
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
@ -64,12 +76,76 @@ 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);
}
});
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", fullNameMy.getText());
context.startActivity(intent);
break;
case R.id.repoWatchers:
Intent intentW = new Intent(context, RepoWatchersActivity.class);
intentW.putExtra("repoFullNameForWatchers", fullNameMy.getText());
context.startActivity(intentW);
break;
case R.id.repoOpenInBrowser:
Intent intentOpenInBrowser = new Intent(context, OpenRepoInBrowserActivity.class);
intentOpenInBrowser.putExtra("repoFullNameBrowser", fullNameMy.getText());
context.startActivity(intentOpenInBrowser);
break;
}
return false;
}
});
popupMenu.show();
}
});
}
}
@ -94,19 +170,29 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
String charac = String.valueOf(currentItem.getName().charAt(0));
String firstCharacter = String.valueOf(currentItem.getName().charAt(0));
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.useFont(Typeface.DEFAULT)
.fontSize(16)
.fontSize(18)
.toUpperCase()
.width(28)
.height(28)
.endConfig()
.buildRound(charac, color);
.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.imageMy);
} else {
holder.imageMy.setImageDrawable(drawable);
}
}
else {
holder.imageMy.setImageDrawable(drawable);
}
holder.imageMy.setImageDrawable(drawable);
holder.mTextView1My.setText(currentItem.getName());
if (!currentItem.getDescription().equals("")) {
holder.mTextView2My.setVisibility(View.VISIBLE);
@ -115,12 +201,14 @@ 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.repoWatchersMy.setText(currentItem.getWatchers_count());
holder.repoForksMy.setText(currentItem.getForks_count());
holder.repoOpenIssuesCountMy.setText(currentItem.getOpen_issues_count());
}

View File

@ -76,11 +76,10 @@ public class OrganizationsListAdapter extends RecyclerView.Adapter<Organizations
@Override
public void onBindViewHolder(@NonNull OrganizationsViewHolder holder, int position) {
UserOrganizations currentItem = orgList.get(position);
holder.mTextView2.setVisibility(View.GONE);
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(holder.image);
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
holder.mTextView1.setText(currentItem.getUsername());
if (!currentItem.getDescription().equals("")) {
holder.mTextView2.setVisibility(View.VISIBLE);

View File

@ -65,7 +65,7 @@ public class ProfileFollowersAdapter extends RecyclerView.Adapter<ProfileFollowe
holder.userName.setVisibility(View.GONE);
}
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(100, 0)).resize(140, 140).centerCrop().into(holder.userAvatar);
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
}
@Override

View File

@ -65,7 +65,7 @@ public class ProfileFollowingAdapter extends RecyclerView.Adapter<ProfileFollowi
holder.userName.setVisibility(View.GONE);
}
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(100, 0)).resize(140, 140).centerCrop().into(holder.userAvatar);
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
}
@Override

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

@ -1,7 +1,11 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Html;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -11,22 +15,30 @@ import com.amulyakhare.textdrawable.TextDrawable;
import com.vdurmont.emoji.EmojiParser;
import org.mian.gitnex.R;
import org.mian.gitnex.models.Releases;
import org.mian.gitnex.util.TinyDB;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import okhttp3.OkHttpClient;
import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.Markwon;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import ru.noties.markwon.ext.tables.TablePlugin;
import ru.noties.markwon.ext.tasklist.TaskListPlugin;
import ru.noties.markwon.html.HtmlPlugin;
import ru.noties.markwon.image.ImagesPlugin;
import ru.noties.markwon.image.gif.GifPlugin;
import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin;
import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin;
import io.noties.markwon.core.MarkwonTheme;
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tasklist.TaskListPlugin;
import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.AsyncDrawable;
import io.noties.markwon.image.DefaultMediaDecoder;
import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin;
import io.noties.markwon.image.SchemeHandler;
import io.noties.markwon.image.gif.GifMediaDecoder;
import io.noties.markwon.image.svg.SvgMediaDecoder;
import io.noties.markwon.linkify.LinkifyPlugin;
/**
* Author M M Arif
@ -75,6 +87,8 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
@Override
public void onBindViewHolder(@NonNull ReleasesAdapter.ReleasesViewHolder holder, int position) {
final TinyDB tinyDb = new TinyDB(mCtx);
Releases currentItem = releasesList.get(position);
holder.releaseTitle.setText(currentItem.getName());
@ -113,34 +127,77 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
final Markwon markwon = Markwon.builder(Objects.requireNonNull(mCtx))
.usePlugin(CorePlugin.create())
.usePlugin(OkHttpImagesPlugin.create(new OkHttpClient()))
.usePlugin(ImagesPlugin.createWithAssets(mCtx))
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
@Override
public void configureImages(@NonNull ImagesPlugin plugin) {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = mCtx.getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
mCtx.getPackageName());
final Drawable drawable = mCtx.getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
@Nullable
@Override
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
return null;
}
});
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder
.codeTextColor(Color.GREEN)
.codeBackgroundColor(Color.BLACK)
.codeTextColor(tinyDb.getInt("codeBlockColor"))
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(mCtx.getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(mCtx))
.usePlugin(TaskListPlugin.create(mCtx))
.usePlugin(HtmlPlugin.create())
.usePlugin(GifPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(currentItem.getBody()));
Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(currentItem.getBody()));
if(!currentItem.getBody().equals("")) {
holder.releaseDescription.setText(bodyWithMD);
markwon.setParsedMarkdown(holder.releaseDescription, bodyWithMD);
}
else {
holder.releaseDescription.setVisibility(View.GONE);
}
holder.releaseZipDownload.setText(currentItem.getZipball_url());
holder.releaseTarDownload.setText(currentItem.getTarball_url());
holder.releaseZipDownload.setText(
Html.fromHtml("<a href='" + currentItem.getZipball_url() + "'>" + mCtx.getResources().getString(R.string.zipArchiveDownloadReleasesTab) + "</a> "));
holder.releaseZipDownload.setMovementMethod(LinkMovementMethod.getInstance());
holder.releaseTarDownload.setText(
Html.fromHtml("<a href='" + currentItem.getTarball_url() + "'>" + mCtx.getResources().getString(R.string.tarArchiveDownloadReleasesTab) + "</a> "));
holder.releaseTarDownload.setMovementMethod(LinkMovementMethod.getInstance());
}

View File

@ -0,0 +1,126 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
/**
* Author M M Arif
*/
public class RepoStargazersAdapter extends BaseAdapter {
private List<UserInfo> stargazersList;
private Context mCtx;
private static class ViewHolder {
private ImageView memberAvatar;
private TextView memberName;
ViewHolder(View v) {
memberAvatar = v.findViewById(R.id.memberAvatar);
memberName = v.findViewById(R.id.memberName);
}
}
public RepoStargazersAdapter(Context mCtx, List<UserInfo> membersListMain) {
this.mCtx = mCtx;
this.stargazersList = membersListMain;
}
@Override
public int getCount() {
return stargazersList.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@SuppressLint("InflateParams")
@Override
public View getView(int position, View finalView, ViewGroup parent) {
RepoStargazersAdapter.ViewHolder viewHolder;
if (finalView == null) {
finalView = LayoutInflater.from(mCtx).inflate(R.layout.repo_stargazers_list, null);
viewHolder = new ViewHolder(finalView);
finalView.setTag(viewHolder);
}
else {
viewHolder = (RepoStargazersAdapter.ViewHolder) finalView.getTag();
}
initData(viewHolder, position);
return finalView;
}
private void initData(RepoStargazersAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = stargazersList.get(position);
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.memberAvatar);
final TinyDB tinyDb = new TinyDB(mCtx);
Typeface myTypeface;
if(tinyDb.getInt("customFontId") == 0) {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/roboto.ttf");
}
else if (tinyDb.getInt("customFontId") == 1) {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/manroperegular.ttf");
}
else if (tinyDb.getInt("customFontId") == 2) {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/sourcecodeproregular.ttf");
}
else {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/roboto.ttf");
}
if(!currentItem.getFullname().equals("")) {
viewHolder.memberName.setText(currentItem.getFullname());
viewHolder.memberName.setTypeface(myTypeface);
}
else {
viewHolder.memberName.setText(currentItem.getLogin());
viewHolder.memberName.setTypeface(myTypeface);
}
if(tinyDb.getInt("themeId") == 1) { //light
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.lightThemeTextColor));
}
else { // dark
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.white));
}
}
}

View File

@ -0,0 +1,126 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
/**
* Author M M Arif
*/
public class RepoWatchersAdapter extends BaseAdapter {
private List<UserInfo> watchersList;
private Context mCtx;
private static class ViewHolder {
private ImageView memberAvatar;
private TextView memberName;
ViewHolder(View v) {
memberAvatar = v.findViewById(R.id.memberAvatar);
memberName = v.findViewById(R.id.memberName);
}
}
public RepoWatchersAdapter(Context mCtx, List<UserInfo> membersListMain) {
this.mCtx = mCtx;
this.watchersList = membersListMain;
}
@Override
public int getCount() {
return watchersList.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@SuppressLint("InflateParams")
@Override
public View getView(int position, View finalView, ViewGroup parent) {
RepoWatchersAdapter.ViewHolder viewHolder;
if (finalView == null) {
finalView = LayoutInflater.from(mCtx).inflate(R.layout.repo_watchers_list, null);
viewHolder = new ViewHolder(finalView);
finalView.setTag(viewHolder);
}
else {
viewHolder = (RepoWatchersAdapter.ViewHolder) finalView.getTag();
}
initData(viewHolder, position);
return finalView;
}
private void initData(RepoWatchersAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = watchersList.get(position);
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.memberAvatar);
final TinyDB tinyDb = new TinyDB(mCtx);
Typeface myTypeface;
if(tinyDb.getInt("customFontId") == 0) {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/roboto.ttf");
}
else if (tinyDb.getInt("customFontId") == 1) {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/manroperegular.ttf");
}
else if (tinyDb.getInt("customFontId") == 2) {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/sourcecodeproregular.ttf");
}
else {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/roboto.ttf");
}
if(!currentItem.getFullname().equals("")) {
viewHolder.memberName.setText(currentItem.getFullname());
viewHolder.memberName.setTypeface(myTypeface);
}
else {
viewHolder.memberName.setText(currentItem.getLogin());
viewHolder.memberName.setTypeface(myTypeface);
}
if(tinyDb.getInt("themeId") == 1) { //light
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.lightThemeTextColor));
}
else { // dark
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.white));
}
}
}

View File

@ -4,8 +4,11 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import androidx.annotation.NonNull;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
@ -14,10 +17,16 @@ import android.widget.ImageView;
import android.widget.TextView;
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.ArrayList;
import java.util.List;
@ -39,10 +48,12 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
private TextView fullName;
private ImageView repoPrivatePublic;
private TextView repoStars;
private TextView repoWatchers;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private ReposViewHolder(View itemView) {
super(itemView);
mTextView1 = itemView.findViewById(R.id.repoName);
mTextView2 = itemView.findViewById(R.id.repoDescription);
@ -50,26 +61,95 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
fullName = itemView.findViewById(R.id.repoFullName);
repoPrivatePublic = itemView.findViewById(R.id.imageRepoType);
repoStars = itemView.findViewById(R.id.repoStars);
repoWatchers = itemView.findViewById(R.id.repoWatchers);
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
public void onClick(View v) {
Context context = v.getContext();
TextView repoFullName = (TextView) v.findViewById(R.id.repoFullName);
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);
}
});
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 };
assert menuHelper != null;
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();
}
});
}
}
@ -94,19 +174,29 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
String charac = String.valueOf(currentItem.getName().charAt(0));
String firstCharacter = String.valueOf(currentItem.getName().charAt(0));
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.useFont(Typeface.DEFAULT)
.fontSize(16)
.fontSize(18)
.toUpperCase()
.width(28)
.height(28)
.endConfig()
.buildRound(charac, color);
.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.image.setImageDrawable(drawable);
holder.mTextView1.setText(currentItem.getName());
if (!currentItem.getDescription().equals("")) {
holder.mTextView2.setVisibility(View.VISIBLE);
@ -115,12 +205,14 @@ 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.repoWatchers.setText(currentItem.getWatchers_count());
holder.repoForks.setText(currentItem.getForks_count());
holder.repoOpenIssuesCount.setText(currentItem.getOpen_issues_count());
}

View File

@ -4,6 +4,7 @@ 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.Filter;
@ -12,13 +13,21 @@ import android.widget.ImageView;
import android.widget.TextView;
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.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
/**
@ -39,8 +48,9 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
private TextView fullName;
private ImageView repoPrivatePublic;
private TextView repoStars;
private TextView repoWatchers;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private OrgReposViewHolder(View itemView) {
super(itemView);
@ -50,8 +60,10 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
fullName = itemView.findViewById(R.id.repoFullName);
repoPrivatePublic = itemView.findViewById(R.id.imageRepoType);
repoStars = itemView.findViewById(R.id.repoStars);
repoWatchers = itemView.findViewById(R.id.repoWatchers);
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
@ -64,12 +76,76 @@ 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);
}
});
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();
}
});
}
}
@ -95,19 +171,29 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
String charac = String.valueOf(currentItem.getName().charAt(0));
String firstCharacter = String.valueOf(currentItem.getName().charAt(0));
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.useFont(Typeface.DEFAULT)
.fontSize(16)
.fontSize(18)
.toUpperCase()
.width(28)
.height(28)
.endConfig()
.buildRound(charac, color);
.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.image.setImageDrawable(drawable);
holder.mTextView1.setText(currentItem.getName());
if (!currentItem.getDescription().equals("")) {
holder.mTextView2.setVisibility(View.VISIBLE);
@ -116,12 +202,14 @@ 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.repoWatchers.setText(currentItem.getWatchers_count());
holder.repoForks.setText(currentItem.getForks_count());
holder.repoOpenIssuesCount.setText(currentItem.getOpen_issues_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

@ -4,6 +4,7 @@ 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.Filter;
@ -12,13 +13,21 @@ import android.widget.ImageView;
import android.widget.TextView;
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.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
/**
@ -39,8 +48,9 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
private TextView fullName;
private ImageView repoPrivatePublic;
private TextView repoStars;
private TextView repoWatchers;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private StarredReposViewHolder(View itemView) {
super(itemView);
@ -50,8 +60,10 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
fullName = itemView.findViewById(R.id.repoFullName);
repoPrivatePublic = itemView.findViewById(R.id.imageRepoType);
repoStars = itemView.findViewById(R.id.repoStars);
repoWatchers = itemView.findViewById(R.id.repoWatchers);
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
@ -64,12 +76,76 @@ 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);
}
});
reposDropdownMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Context context = v.getContext();
Context context_ = new ContextThemeWrapper(context, R.style.AppThemeConfirmDialog);
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();
}
});
}
}
@ -95,19 +171,29 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
String charac = String.valueOf(currentItem.getName().charAt(0));
String firstCharacter = String.valueOf(currentItem.getName().charAt(0));
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.useFont(Typeface.DEFAULT)
.fontSize(16)
.fontSize(18)
.toUpperCase()
.width(28)
.height(28)
.endConfig()
.buildRound(charac, color);
.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.image.setImageDrawable(drawable);
holder.mTextView1.setText(currentItem.getName());
if (!currentItem.getDescription().equals("")) {
holder.mTextView2.setVisibility(View.VISIBLE);
@ -116,12 +202,14 @@ 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.repoWatchers.setText(currentItem.getWatchers_count());
holder.repoForks.setText(currentItem.getForks_count());
holder.repoOpenIssuesCount.setText(currentItem.getOpen_issues_count());
}

View File

@ -2,6 +2,7 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -12,6 +13,7 @@ import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
/**
@ -23,7 +25,7 @@ public class TeamMembersByOrgAdapter extends BaseAdapter {
private List<UserInfo> teamMembersList;
private Context mCtx;
private class ViewHolder {
private static class ViewHolder {
private ImageView memberAvatar;
private TextView memberName;
@ -63,7 +65,7 @@ public class TeamMembersByOrgAdapter extends BaseAdapter {
if (finalView == null) {
finalView = LayoutInflater.from(mCtx).inflate(R.layout.members_by_team_by_org_list, null);
viewHolder = new TeamMembersByOrgAdapter.ViewHolder(finalView);
viewHolder = new ViewHolder(finalView);
finalView.setTag(viewHolder);
}
else {
@ -78,13 +80,46 @@ public class TeamMembersByOrgAdapter extends BaseAdapter {
private void initData(TeamMembersByOrgAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = teamMembersList.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);
final TinyDB tinyDb = new TinyDB(mCtx);
Typeface myTypeface;
if(tinyDb.getInt("customFontId") == 0) {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/roboto.ttf");
}
else if (tinyDb.getInt("customFontId") == 1) {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/manroperegular.ttf");
}
else if (tinyDb.getInt("customFontId") == 2) {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/sourcecodeproregular.ttf");
}
else {
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/roboto.ttf");
}
if(!currentItem.getFullname().equals("")) {
viewHolder.memberName.setText(currentItem.getFullname());
viewHolder.memberName.setTypeface(myTypeface);
}
else {
viewHolder.memberName.setText(currentItem.getLogin());
viewHolder.memberName.setTypeface(myTypeface);
}
if(tinyDb.getInt("themeId") == 1) { //light
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.lightThemeTextColor));
}
else { // dark
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.white));
}
}

View File

@ -68,7 +68,7 @@ public class UserSearchAdapter extends RecyclerView.Adapter<UserSearchAdapter.Us
final Context context = v.getContext();
AlertDialog.Builder pBuilder = new AlertDialog.Builder(context, R.style.confirmDialog);
AlertDialog.Builder pBuilder = new AlertDialog.Builder(context);
pBuilder.setTitle(R.string.newTeamPermission);
pBuilder.setSingleChoiceItems(permissionList, permissionSelectedChoice, new DialogInterface.OnClickListener() {
@ -141,7 +141,7 @@ public class UserSearchAdapter extends RecyclerView.Adapter<UserSearchAdapter.Us
}
if (!currentItem.getAvatar().equals("")) {
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(holder.userAvatar);
Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
}
if(getItemCount() > 0) {
@ -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,27 @@ 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 +71,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 +113,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

@ -0,0 +1,57 @@
package org.mian.gitnex.fragments;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.mian.gitnex.R;
/**
* Author M M Arif
*/
public class BottomSheetFileViewerFragment extends BottomSheetDialogFragment {
private BottomSheetFileViewerFragment.BottomSheetListener bmListener;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.bottom_sheet_file_viewer, container, false);
TextView downloadFile = v.findViewById(R.id.downloadFile);
downloadFile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bmListener.onButtonClicked("downloadFile");
dismiss();
}
});
return v;
}
public interface BottomSheetListener {
void onButtonClicked(String text);
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
bmListener = (BottomSheetFileViewerFragment.BottomSheetListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement BottomSheetListener");
}
}
}

View File

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -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);
}
@ -125,9 +125,9 @@ public class BranchesFragment extends Fragment {
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner, String repo) {
BranchesViewModel branchesModel = ViewModelProviders.of(this).get(BranchesViewModel.class);
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;
@ -52,6 +51,8 @@ public class ClosedIssuesFragment extends Fragment {
private int pageSize = 1;
private TextView noDataIssuesClosed;
private String issueState = "closed";
private int resultLimit = 50;
private String requestType = "issues";
@Nullable
@Override
@ -87,7 +88,7 @@ public class ClosedIssuesFragment extends Fragment {
public void run() {
swipeRefresh.setRefreshing(false);
loadInitial(instanceToken, repoOwner, repoName, issueState);
loadInitial(instanceToken, repoOwner, repoName, issueState, resultLimit, requestType);
adapterClosed.notifyDataChanged();
}
@ -106,7 +107,7 @@ public class ClosedIssuesFragment extends Fragment {
if(issuesListClosed.size() == 10 || pageSize == 10) {
int page = (issuesListClosed.size() + 10) / 10;
loadMore(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, page, issueState);
loadMore(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, page, issueState, resultLimit, requestType);
}
/*else {
@ -120,15 +121,12 @@ 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);
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, issueState);
apiClosed = IssuesService.createService(ApiInterface.class, instanceUrl, getContext());
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, issueState, resultLimit, requestType);
return v;
@ -148,16 +146,16 @@ public class ClosedIssuesFragment extends Fragment {
if(tinyDb.getBoolean("resumeClosedIssues")) {
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, issueState);
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, issueState, resultLimit, requestType);
tinyDb.putBoolean("resumeClosedIssues", false);
}
}
private void loadInitial(String token, String repoOwner, String repoName, String issueState) {
private void loadInitial(String token, String repoOwner, String repoName, String issueState, int resultLimit, String requestType) {
Call<List<Issues>> call = apiClosed.getClosedIssues(token, repoOwner, repoName, 1, issueState);
Call<List<Issues>> call = apiClosed.getClosedIssues(token, repoOwner, repoName, 1, issueState, resultLimit, requestType);
call.enqueue(new Callback<List<Issues>>() {
@ -190,20 +188,20 @@ 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());
}
});
}
private void loadMore(String token, String repoOwner, String repoName, int page, String issueState){
private void loadMore(String token, String repoOwner, String repoName, int page, String issueState, int resultLimit, String requestType){
//add loading progress view
issuesListClosed.add(new Issues("load"));
adapterClosed.notifyItemInserted((issuesListClosed.size() - 1));
Call<List<Issues>> call = apiClosed.getClosedIssues(token, repoOwner, repoName, page, issueState);
Call<List<Issues>> call = apiClosed.getClosedIssues(token, repoOwner, repoName, page, issueState, resultLimit, requestType);
call.enqueue(new Callback<List<Issues>>() {
@ -245,7 +243,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,10 +261,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));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {

View File

@ -6,11 +6,12 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.CollaboratorsAdapter;
@ -26,6 +27,7 @@ import java.util.List;
public class CollaboratorsFragment extends Fragment {
private ProgressBar mProgressBar;
private CollaboratorsAdapter adapter;
private GridView mGridView;
private TextView noDataCollaborators;
@ -69,6 +71,8 @@ public class CollaboratorsFragment extends Fragment {
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
noDataCollaborators = v.findViewById(R.id.noDataCollaborators);
mProgressBar = v.findViewById(R.id.progress_bar);
mGridView = v.findViewById(R.id.gridView);
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
@ -94,9 +98,9 @@ public class CollaboratorsFragment extends Fragment {
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner, String repo) {
CollaboratorsViewModel collaboratorsModel = ViewModelProviders.of(this).get(CollaboratorsViewModel.class);
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);
@ -109,6 +113,7 @@ public class CollaboratorsFragment extends Fragment {
mGridView.setAdapter(adapter);
noDataCollaborators.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
}
});

View File

@ -0,0 +1,216 @@
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.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.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) {
final View v = inflater.inflate(R.layout.fragment_explore_repo, 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");
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);
mProgressBar.setVisibility(View.VISIBLE);
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;
}
});
int limitDefault = 10;
loadDefaultList(instanceUrl, instanceToken, loginUid, repoTypeInclude, sort, order, getContext(), limitDefault);
return v;
}
private void loadDefaultList(String instanceUrl, String instanceToken, String loginUid, 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), null, 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 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,308 @@
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());
String currentIndex = (result + item.getSelectedItem()).substring(1);
fetchDataAsyncSub(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, currentIndex);
}
@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;
@ -51,6 +50,8 @@ public class IssuesFragment extends Fragment {
private Context context;
private int pageSize = 1;
private TextView noDataIssues;
private int resultLimit = 50;
private String requestType = "issues";
@Nullable
@Override
@ -86,7 +87,7 @@ public class IssuesFragment extends Fragment {
public void run() {
swipeRefresh.setRefreshing(false);
loadInitial(instanceToken, repoOwner, repoName);
loadInitial(instanceToken, repoOwner, repoName, resultLimit, requestType);
adapter.notifyDataChanged();
}
@ -105,7 +106,7 @@ public class IssuesFragment extends Fragment {
if(issuesList.size() == 10 || pageSize == 10) {
int page = (issuesList.size() + 10) / 10;
loadMore(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, page);
loadMore(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, page, resultLimit, requestType);
}
/*else {
@ -119,15 +120,12 @@ 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);
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
api = IssuesService.createService(ApiInterface.class, instanceUrl, getContext());
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, resultLimit, requestType);
return v;
@ -147,16 +145,16 @@ public class IssuesFragment extends Fragment {
if(tinyDb.getBoolean("resumeIssues")) {
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
loadInitial(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, resultLimit, requestType);
tinyDb.putBoolean("resumeIssues", false);
}
}
private void loadInitial(String token, String repoOwner, String repoName) {
private void loadInitial(String token, String repoOwner, String repoName, int resultLimit, String requestType) {
Call<List<Issues>> call = api.getIssues(token, repoOwner, repoName, 1);
Call<List<Issues>> call = api.getIssues(token, repoOwner, repoName, 1, resultLimit, requestType);
call.enqueue(new Callback<List<Issues>>() {
@ -189,20 +187,20 @@ 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());
}
});
}
private void loadMore(String token, String repoOwner, String repoName, int page){
private void loadMore(String token, String repoOwner, String repoName, int page, int resultLimit, String requestType){
//add loading progress view
issuesList.add(new Issues("load"));
adapter.notifyItemInserted((issuesList.size() - 1));
Call<List<Issues>> call = api.getIssues(token, repoOwner, repoName, page);
Call<List<Issues>> call = api.getIssues(token, repoOwner, repoName, page, resultLimit, requestType);
call.enqueue(new Callback<List<Issues>>() {
@ -244,7 +242,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,10 +260,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));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {

View File

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -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);
}
}
@ -142,9 +142,9 @@ public class LabelsFragment extends Fragment {
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner, String repo) {
LabelsViewModel labelsModel = ViewModelProviders.of(this).get(LabelsViewModel.class);
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

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -81,9 +81,9 @@ public class MembersByOrgFragment extends Fragment {
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner) {
MembersByOrgViewModel membersModel = ViewModelProviders.of(this).get(MembersByOrgViewModel.class);
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,6 +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));
if(!connToInternet) {
return;
@ -125,7 +126,9 @@ public class MembersByOrgFragment extends Fragment {
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
if(mGridView.getAdapter() != null) {
adapter.getFilter().filter(newText);
}
return false;
}
});

View File

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -46,6 +46,7 @@ public class MilestonesFragment extends Fragment {
private String repoName;
private String repoOwner;
private String msState = "all";
private OnFragmentInteractionListener mListener;
@ -103,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);
MilestonesViewModel.loadMilestonesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, msState, getContext());
}
}, 50);
}
@ -127,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);
MilestonesViewModel.loadMilestonesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, msState, getContext());
tinyDb.putBoolean("milestoneCreated", false);
}
}
@ -150,9 +151,9 @@ public class MilestonesFragment extends Fragment {
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner, String repo) {
MilestonesViewModel msModel = ViewModelProviders.of(this).get(MilestonesViewModel.class);
MilestonesViewModel msModel = new ViewModelProvider(this).get(MilestonesViewModel.class);
msModel.getMilestonesList(instanceUrl, instanceToken, owner, repo).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);
@ -182,10 +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));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
@ -195,7 +197,9 @@ public class MilestonesFragment extends Fragment {
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
if(mRecyclerView.getAdapter() != null) {
adapter.getFilter().filter(newText);
}
return false;
}
});

View File

@ -7,7 +7,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -24,7 +24,6 @@ import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.activities.NewRepoActivity;
import org.mian.gitnex.adapters.MyReposListAdapter;
import org.mian.gitnex.helpers.Authorization;
@ -49,6 +48,9 @@ public class MyRepositoriesFragment extends Fragment {
private ImageView createNewRepo;
private TextView noDataMyRepo;
private int pageSize = 1;
private int resultLimit = 50;
private String mParam1;
private String mParam2;
@ -83,12 +85,12 @@ public class MyRepositoriesFragment extends Fragment {
final View v = inflater.inflate(R.layout.fragment_my_repositories, container, false);
setHasOptionsMenu(true);
((MainActivity) Objects.requireNonNull(getActivity())).setActionBarTitle(getResources().getString(R.string.pageTitleMyRepos));
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");
final String userLogin = tinyDb.getString("userLogin");
final SwipeRefreshLayout swipeRefresh = v.findViewById(R.id.pullToRefresh);
@ -131,27 +133,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(), pageSize, resultLimit);
}
}, 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, pageSize, resultLimit);
return v;
@ -164,16 +159,20 @@ 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);
if(tinyDb.getBoolean("repoCreated")) {
MyRepositoriesViewModel.loadMyReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), userLogin, getContext(), pageSize, resultLimit);
tinyDb.putBoolean("repoCreated", false);
}
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String username) {
private void fetchDataAsync(String instanceUrl, String instanceToken, String userLogin, int pageSize, int resultLimit) {
MyRepositoriesViewModel myRepoModel = ViewModelProviders.of(this).get(MyRepositoriesViewModel.class);
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(), pageSize, resultLimit).observe(getViewLifecycleOwner(), new Observer<List<UserRepositories>>() {
@Override
public void onChanged(@Nullable List<UserRepositories> myReposListMain) {
adapter = new MyReposListAdapter(getContext(), myReposListMain);
@ -203,10 +202,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));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
@ -216,7 +216,9 @@ public class MyRepositoriesFragment extends Fragment {
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
if(mRecyclerView.getAdapter() != null) {
adapter.getFilter().filter(newText);
}
return false;
}
});

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);
@ -104,7 +104,7 @@ public class OrganizationInfoFragment extends Fragment {
if (response.code() == 200) {
assert orgInfo != null;
Picasso.get().load(orgInfo.getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(orgAvatar);
Picasso.get().load(orgInfo.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(orgAvatar);
orgDescInfo.setText(orgInfo.getDescription());
orgWebsiteInfo.setText(orgInfo.getWebsite());
orgLocationInfo.setText(orgInfo.getLocation());

View File

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -23,7 +23,6 @@ import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.activities.NewOrganizationActivity;
import org.mian.gitnex.adapters.OrganizationsListAdapter;
import org.mian.gitnex.helpers.Authorization;
@ -50,7 +49,6 @@ public class OrganizationsFragment extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
((MainActivity) Objects.requireNonNull(getActivity())).setActionBarTitle(getResources().getString(R.string.pageTitleOrganizations));
final View v = inflater.inflate(R.layout.fragment_organizations, container, false);
setHasOptionsMenu(true);
@ -101,25 +99,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,16 +127,16 @@ 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);
}
}
private void fetchDataAsync(String instanceUrl, String instanceToken) {
OrganizationListViewModel orgModel = ViewModelProviders.of(this).get(OrganizationListViewModel.class);
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,10 +166,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));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
@ -186,7 +180,9 @@ public class OrganizationsFragment extends Fragment {
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
if(mRecyclerView.getAdapter() != null) {
adapter.getFilter().filter(newText);
}
return false;
}
});

View File

@ -5,7 +5,7 @@ import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -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);
}
@ -109,9 +109,9 @@ public class ProfileEmailsFragment extends Fragment {
private void fetchDataAsync(String instanceUrl, String instanceToken) {
ProfileEmailsViewModel profileEmailModel = ViewModelProviders.of(this).get(ProfileEmailsViewModel.class);
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

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -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);
}
@ -108,9 +108,9 @@ public class ProfileFollowersFragment extends Fragment {
private void fetchDataAsync(String instanceUrl, String instanceToken) {
ProfileFollowersViewModel pfModel = ViewModelProviders.of(this).get(ProfileFollowersViewModel.class);
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

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -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);
}
@ -108,9 +108,9 @@ public class ProfileFollowingFragment extends Fragment {
private void fetchDataAsync(String instanceUrl, String instanceToken) {
ProfileFollowingViewModel pfModel = ViewModelProviders.of(this).get(ProfileFollowingViewModel.class);
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

@ -1,6 +1,7 @@
package org.mian.gitnex.fragments;
import android.content.Context;
import android.graphics.Typeface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -37,7 +38,6 @@ public class ProfileFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_profile, container, false);
((MainActivity) Objects.requireNonNull(getActivity())).setActionBarTitle(getResources().getString(R.string.pageTitleProfile));
setHasOptionsMenu(true);
TinyDB tinyDb = new TinyDB(getContext());
@ -48,7 +48,7 @@ public class ProfileFragment extends Fragment {
TextView userEmail = v.findViewById(R.id.userEmail);
userFullName.setText(tinyDb.getString("userFullname"));
Picasso.get().load(tinyDb.getString("userAvatar")).transform(new RoundedTransformation(100, 0)).resize(180, 180).centerCrop().into(userAvatar);
Picasso.get().load(tinyDb.getString("userAvatar")).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(userAvatar);
userLogin.setText(getString(R.string.usernameWithAt, tinyDb.getString("userLogin")));
userEmail.setText(tinyDb.getString("userEmail"));
@ -57,8 +57,43 @@ public class ProfileFragment extends Fragment {
ViewPager mViewPager = v.findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
Typeface myTypeface;
if(tinyDb.getInt("customFontId") == 0) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getContext()).getAssets(), "fonts/roboto.ttf");
}
else if (tinyDb.getInt("customFontId") == 1) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getContext()).getAssets(), "fonts/manroperegular.ttf");
}
else if (tinyDb.getInt("customFontId") == 2) {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getContext()).getAssets(), "fonts/sourcecodeproregular.ttf");
}
else {
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getContext()).getAssets(), "fonts/roboto.ttf");
}
TabLayout tabLayout = v.findViewById(R.id.tabs);
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = vg.getChildCount();
for (int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
int tabChildCount = vgTab.getChildCount();
for (int i = 0; i < tabChildCount; i++) {
View tabViewChild = vgTab.getChildAt(i);
if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(myTypeface);
}
}
}
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));

View File

@ -0,0 +1,294 @@
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";
private int resultLimit = 50;
@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, resultLimit);
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, resultLimit);
}
/*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, resultLimit);
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, resultLimit);
tinyDb.putBoolean("resumePullRequests", false);
}
}
private void loadInitial(String token, String repoOwner, String repoName, int page, String prState, int resultLimit) {
Call<List<PullRequests>> call = apiPR.getPullRequests(token, repoOwner, repoName, page, prState, resultLimit);
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, int resultLimit){
//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, resultLimit);
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

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -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);
}
@ -141,9 +141,9 @@ public class ReleasesFragment extends Fragment {
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner, String repo) {
ReleasesViewModel releasesModel = ViewModelProviders.of(this).get(ReleasesViewModel.class);
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,8 @@ 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;
@ -24,11 +26,19 @@ public class RepoBottomSheetFragment extends BottomSheetDialogFragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.repo_bottom_sheet_layout, container, false);
final TinyDB tinyDb = new TinyDB(getContext());
TextView createLabel = v.findViewById(R.id.createLabel);
TextView createIssue = v.findViewById(R.id.createNewIssue);
TextView createMilestone = v.findViewById(R.id.createNewMilestone);
TextView addCollaborator = v.findViewById(R.id.addCollaborator);
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
@ -38,13 +48,19 @@ public class RepoBottomSheetFragment extends BottomSheetDialogFragment {
}
});
createIssue.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bmListener.onButtonClicked("newIssue");
dismiss();
}
});
if(tinyDb.getBoolean("hasIssues")) {
createIssue.setVisibility(View.VISIBLE);
createIssue.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bmListener.onButtonClicked("newIssue");
dismiss();
}
});
}
else {
createIssue.setVisibility(View.GONE);
}
createMilestone.setOnClickListener(new View.OnClickListener() {
@Override
@ -70,6 +86,88 @@ public class RepoBottomSheetFragment extends BottomSheetDialogFragment {
}
});
openWebRepo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bmListener.onButtonClicked("openWebRepo");
dismiss();
}
});
newFile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bmListener.onButtonClicked("newFile");
dismiss();
}
});
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

@ -1,26 +1,31 @@
package org.mian.gitnex.fragments;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import okhttp3.OkHttpClient;
import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin;
import io.noties.markwon.core.MarkwonTheme;
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tasklist.TaskListPlugin;
import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.AsyncDrawable;
import io.noties.markwon.image.DefaultMediaDecoder;
import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin;
import io.noties.markwon.image.SchemeHandler;
import io.noties.markwon.image.gif.GifMediaDecoder;
import io.noties.markwon.image.svg.SvgMediaDecoder;
import io.noties.markwon.linkify.LinkifyPlugin;
import retrofit2.Call;
import retrofit2.Callback;
import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.Markwon;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import ru.noties.markwon.ext.tables.TablePlugin;
import ru.noties.markwon.ext.tables.TableTheme;
import ru.noties.markwon.ext.tasklist.TaskListPlugin;
import ru.noties.markwon.html.HtmlPlugin;
import ru.noties.markwon.image.ImagesPlugin;
import ru.noties.markwon.image.gif.GifPlugin;
import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin;
import android.text.Spanned;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@ -42,6 +47,8 @@ import org.mian.gitnex.util.TinyDB;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.Objects;
@ -208,8 +215,10 @@ public class RepoInfoFragment extends Fragment {
private void getRepoInfo(String instanceUrl, String token, final String owner, String repo, final String locale, final String timeFormat) {
final TinyDB tinyDb = new TinyDB(getContext());
Call<UserRepositories> call = RetrofitClient
.getInstance(instanceUrl)
.getInstance(instanceUrl, getContext())
.getApiInterface()
.getUserRepository(token, owner, repo);
@ -220,53 +229,64 @@ public class RepoInfoFragment extends Fragment {
UserRepositories repoInfo = response.body();
if (response.isSuccessful()) {
if (isAdded()) {
if (response.code() == 200) {
if (response.isSuccessful()) {
assert repoInfo != null;
repoNameInfo.setText(repoInfo.getName());
repoOwnerInfo.setText(owner);
repoDescriptionInfo.setText(repoInfo.getDescription());
repoWebsiteInfo.setText(repoInfo.getWebsite());
repoSizeInfo.setText(AppUtil.formatFileSize(repoInfo.getSize()));
repoDefaultBranchInfo.setText(repoInfo.getDefault_branch());
repoSshUrlInfo.setText(repoInfo.getSsh_url());
repoCloneUrlInfo.setText(repoInfo.getClone_url());
repoRepoUrlInfo.setText(repoInfo.getHtml_url());
repoForksCountInfo.setText(repoInfo.getForks_count());
if (response.code() == 200) {
switch (timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(repoInfo.getCreated_at());
repoCreatedAtInfo.setText(createdTime);
repoCreatedAtInfo.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(repoInfo.getCreated_at()), getContext()));
break;
assert repoInfo != null;
repoNameInfo.setText(repoInfo.getName());
repoOwnerInfo.setText(owner);
repoDescriptionInfo.setText(repoInfo.getDescription());
repoWebsiteInfo.setText(repoInfo.getWebsite());
repoSizeInfo.setText(AppUtil.formatFileSize(repoInfo.getSize()));
repoDefaultBranchInfo.setText(repoInfo.getDefault_branch());
repoSshUrlInfo.setText(repoInfo.getSsh_url());
repoCloneUrlInfo.setText(repoInfo.getClone_url());
repoRepoUrlInfo.setText(repoInfo.getHtml_url());
repoForksCountInfo.setText(repoInfo.getForks_count());
if(repoInfo.getHas_issues() != null) {
tinyDb.putBoolean("hasIssues", repoInfo.getHas_issues());
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(repoInfo.getCreated_at());
repoCreatedAtInfo.setText(createdTime);
break;
else {
tinyDb.putBoolean("hasIssues", true);
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(repoInfo.getCreated_at());
repoCreatedAtInfo.setText(createdTime);
break;
switch (timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(repoInfo.getCreated_at());
repoCreatedAtInfo.setText(createdTime);
repoCreatedAtInfo.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(repoInfo.getCreated_at()), getContext()));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(repoInfo.getCreated_at());
repoCreatedAtInfo.setText(createdTime);
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(repoInfo.getCreated_at());
repoCreatedAtInfo.setText(createdTime);
break;
}
}
mProgressBar.setVisibility(View.GONE);
pageContent.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
pageContent.setVisibility(View.VISIBLE);
}
else {
Log.e("onFailure", String.valueOf(response.code()));
}
}
else {
Log.e("onFailure", String.valueOf(response.code()));
}
}
@ -283,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);
@ -292,12 +312,51 @@ public class RepoInfoFragment extends Fragment {
@Override
public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) {
if (response.code() == 200) {
if (isAdded()) {
final Markwon markwon = Markwon.builder(Objects.requireNonNull(getContext()))
if (response.code() == 200) {
final Markwon markwon = Markwon.builder(Objects.requireNonNull(getContext()))
.usePlugin(CorePlugin.create())
.usePlugin(OkHttpImagesPlugin.create(new OkHttpClient()))
.usePlugin(ImagesPlugin.createWithAssets(getContext()))
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
@Override
public void configureImages(@NonNull ImagesPlugin plugin) {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = getContext().getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
getContext().getPackageName());
final Drawable drawable = getContext().getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
@Nullable
@Override
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
return null;
}
});
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(getContext().getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(getContext().getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
@ -310,40 +369,39 @@ public class RepoInfoFragment extends Fragment {
.usePlugin(TablePlugin.create(getContext()))
.usePlugin(TaskListPlugin.create(getContext()))
.usePlugin(HtmlPlugin.create())
.usePlugin(GifPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
CharSequence bodyWithMD = null;
if (response.body() != null) {
bodyWithMD = markwon.toMarkdown(response.body());
Spanned bodyWithMD = null;
if (response.body() != null) {
bodyWithMD = markwon.toMarkdown(response.body());
}
assert bodyWithMD != null;
markwon.setParsedMarkdown(repoFileContents, bodyWithMD);
} 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) {
fileContentsFrameHeader.setVisibility(View.GONE);
fileContentsFrame.setVisibility(View.GONE);
} else {
Toasty.info(getContext(), getString(R.string.genericError));
}
repoFileContents.setText(bodyWithMD);
}
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) {
fileContentsFrameHeader.setVisibility(View.GONE);
fileContentsFrame.setVisibility(View.GONE);
}
else {
Toasty.info(getContext(), getString(R.string.genericError));
}
}

View File

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -45,6 +45,8 @@ public class RepositoriesByOrgFragment extends Fragment {
private TextView noData;
private static String orgNameF = "param2";
private String orgName;
private int pageSize = 1;
private int resultLimit = 50;
public RepositoriesByOrgFragment() {
}
@ -97,13 +99,13 @@ 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(), pageSize, resultLimit);
}
}, 200);
}
});
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName);
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName, pageSize, resultLimit);
return v;
}
@ -117,15 +119,18 @@ 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);
if(tinyDb.getBoolean("repoCreated")) {
RepositoriesByOrgViewModel.loadOrgRepos(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName, getContext(), pageSize, resultLimit);
tinyDb.putBoolean("repoCreated", false);
}
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner) {
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner, int pageSize, int resultLimit) {
RepositoriesByOrgViewModel orgRepoModel = ViewModelProviders.of(this).get(RepositoriesByOrgViewModel.class);
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(), pageSize, resultLimit).observe(getViewLifecycleOwner(), new Observer<List<UserRepositories>>() {
@Override
public void onChanged(@Nullable List<UserRepositories> orgReposListMain) {
adapter = new RepositoriesByOrgAdapter(getContext(), orgReposListMain);
@ -155,6 +160,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));
if(!connToInternet) {
return;
@ -168,7 +174,9 @@ public class RepositoriesByOrgFragment extends Fragment {
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
if(mRecyclerView.getAdapter() != null) {
adapter.getFilter().filter(newText);
}
return false;
}
});

View File

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -22,7 +22,6 @@ import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.activities.NewRepoActivity;
import org.mian.gitnex.adapters.ReposListAdapter;
import org.mian.gitnex.helpers.Authorization;
@ -45,6 +44,8 @@ public class RepositoriesFragment extends Fragment {
private ReposListAdapter adapter;
private ImageView createNewRepo;
private TextView noDataRepo;
private int pageSize = 1;
private int resultLimit = 50;
@Nullable
@Override
@ -54,7 +55,6 @@ public class RepositoriesFragment extends Fragment {
final View v = inflater.inflate(R.layout.fragment_repositories, container, false);
setHasOptionsMenu(true);
((MainActivity) Objects.requireNonNull(getActivity())).setActionBarTitle(getResources().getString(R.string.pageTitleRepositories));
TinyDB tinyDb = new TinyDB(getContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
@ -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(), pageSize, resultLimit);
}
}, 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), pageSize, resultLimit);
return v;
@ -137,16 +130,16 @@ 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(), pageSize, resultLimit);
tinyDb.putBoolean("repoCreated", false);
}
}
private void fetchDataAsync(String instanceUrl, String instanceToken) {
private void fetchDataAsync(String instanceUrl, String instanceToken, int pageSize, int resultLimit) {
RepositoriesListViewModel repoModel = ViewModelProviders.of(this).get(RepositoriesListViewModel.class);
RepositoriesListViewModel repoModel = new ViewModelProvider(this).get(RepositoriesListViewModel.class);
repoModel.getUserRepositories(instanceUrl, instanceToken).observe(this, new Observer<List<UserRepositories>>() {
repoModel.getUserRepositories(instanceUrl, instanceToken, getContext(), pageSize, resultLimit).observe(getViewLifecycleOwner(), new Observer<List<UserRepositories>>() {
@Override
public void onChanged(@Nullable List<UserRepositories> reposListMain) {
adapter = new ReposListAdapter(getContext(), reposListMain);
@ -176,10 +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));
if(!connToInternet) {
/*if(!connToInternet) {
return;
}
}*/
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
@ -189,7 +183,9 @@ public class RepositoriesFragment extends Fragment {
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
if(mRecyclerView.getAdapter() != null) {
adapter.getFilter().filter(newText);
}
return false;
}
});

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