Compare commits

..

123 Commits

Author SHA1 Message Date
495c9b4179 Prepare release 4.1.0 (#994)
Closes #978

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/994
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-10-12 18:39:45 +02:00
122c5c068d Crowdin 2021-10-06 (#991)
as title

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/991
Reviewed-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-authored-by: 6543 <6543@noreply.codeberg.org>
Co-committed-by: 6543 <6543@noreply.codeberg.org>
2021-10-06 17:13:50 +02:00
a08cf13382 Render md in org/repo info (#986)
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-10-05 17:16:22 +02:00
ba930021e7 Allow nav from issue to repo when coming from explore/notifications (#988)
Adds the navigation to explore/notifications too
closes #747

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/988
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-10-04 21:08:34 +02:00
6d9a64596f Center icons (#987)
As discussed in Discord

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/987
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-10-04 21:07:57 +02:00
22cd23525e Explore users (#972)
Closes #960

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/972
Reviewed-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-10-04 15:35:34 +02:00
f4cd3c9a4d Refactors and clean up (#979)
Related #278

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/979
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-09-29 11:29:39 +02:00
b493dfc567 Filter issues by milestone (#980)
Closes #693

Right now I like how the API(filters) is for issues, for PRs it is only accepting Ids. It should be more like issues which has optional titles and more forgiving.

Maybe in the future will implement for PRs when the API become updated.

Issues:
https://codeberg.org/api/swagger#/issue/issueListIssues

PR:
https://codeberg.org/api/swagger#/repository/repoListPullRequests

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/980
Reviewed-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-09-28 11:10:27 +02:00
95aea16a07 Add option to update PR (#973)
### Describe what your pull request does and which issue you’re targeting
<!-- Create a new issue, if it doesn't exist yet -->
Closes #967
<br><br>

<!-- Make sure you are targeting the "main" branch, pull requests on release branches are only allowed for bug fixes. -->

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/973
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-09-14 16:18:28 +02:00
77d1d448ba Fix visibility of "Mark as read" button (#975)
### Describe what your pull request does and which issue you’re targeting
<!-- Create a new issue, if it doesn't exist yet -->
Closes #970
<br><br>

<!-- Make sure you are targeting the "main" branch, pull requests on release branches are only allowed for bug fixes. -->

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/975
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-09-02 08:52:18 +02:00
2659d87bbe Re-enable single release handler (#974)
Was disabled in #958 due to crashes related to this. This re-enables it but fixes the crashes.
Also adresses #955

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/974
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-09-02 08:07:11 +02:00
3a38e4d7d5 Add options to follow and unfollow users (#971)
### Describe what your pull request does and which issue you’re targeting
<!-- Create a new issue, if it doesn't exist yet -->
Adds options to follow and unfollow users. Closes #968
<br><br>

<!-- Make sure you are targeting the "main" branch, pull requests on release branches are only allowed for bug fixes. -->

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/971
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-08-31 09:33:26 +02:00
244dc12fc3 Kick start 4.1.0 (#966)
As title

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/966
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-08-24 21:29:34 +02:00
8ea7e470c5 Prepare release 4.0.0 (#963)
Closes #956

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/963
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-08-16 09:04:43 +02:00
77edf450c6 Translation updates (#962)
As title

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/962
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-08-16 08:37:23 +02:00
e0ff35d530 [BUG] Releases should come before release tag (#958)
As title

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/958
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-08-15 19:36:12 +02:00
f88a2df749 Enable user link handler and fix click on users in admin section (#957)
addresses #955
This pr does the following:
1. enables the users link handler
2. it allows clicks on the full `itemView` in the admin users section (related to https://codeberg.org/gitnex/GitNex/pulls/931#issuecomment-211296)

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/957
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-08-11 14:47:31 +02:00
bb392fb639 Fix biometric bug in recent apps (#940)
Closes #930

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: 6543 <6543@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/940
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-08-03 09:41:40 +02:00
1693acaa70 User profile view (#931)
Closes #881

Please suggest on current data shown as some may be related to personal(email etc), but at this moment we have not much to show either. So sticking to it is my view on this.

I will extend the taps on profile images once we agree what to show.

@gitnex/Code-Managers

- [x] Detail
- [x] Repositories
- [x] Starred Repos
- [x] Followers
- [x] Following
- [x] Tap on all profile images
- [x] Organizations

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: opyale <opyale@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/931
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-08-02 20:04:33 +02:00
1e8c8efd6b Fix md rendering after editing file (#954)
### Describe what your pull request does and which issue you’re targeting
fixes #951
and you can review/merge it

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/954
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-08-02 19:22:49 +02:00
5544ae4248 Add option to change times that are used to switch to light/dark theme (#932)
### Describe what your pull request does and which issue you’re targeting
Closes #928

This allows to select the time to switch between themes. The mentioned color/contrast problem with the time selection isn't fixed. I also simplified the settings code (0fe854fd49). And with [this](a590f5bc4c) GitNex hides the two options to change the time if your theme isn't `Auto (Light/Dark)` or `Auto (Retro/Dark)`. I could apply this also to the notifications settings, that means that the advanced settings for notifications (polling delay, light...) are hidden if the notifications aren't enabled.

this is ready to review/merge
<br><br>

<!-- Make sure you are targeting the "main" branch, pull requests on release branches are only allowed for bug fixes. -->

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/932
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-08-02 18:59:30 +02:00
36f20bb1aa Add more link handlers (#948)
I can't implement every handler correctly, if there are no views that display them (e.g. a single milestone or release)

- [X] Organization #915
- [X] Milestones
- [X] Milestone
- [X] New milestone
- [X] Files
- [ ] Lines *currently opens file viewer*
- [X] Folders/directory's
- [X] Branches list
- [X] Branches
- [X] Releases
- [X] Release
- [X] new Release
- [X] Labels
- [X] Explore (orgs/repos)
- [X] Commits list
- [X] New issue
- [ ] Issue comments *currently opens the issue details*
- [X] New PR
- [ ] PR comments *currently opens the PR details*
- [X] PR diff
- [X] Your user profile
- [ ] User profiles *blocked by #931*
- [X] Gitea administration
- [X] Notifications
- [X] repository settings (only for repo admins)
- [X] Login screen

Commits: not possible, Gitea's API doesn't provide enough information to view the correct branch in the list and/or to display the diff.

Closes #918
Closes #915

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/948
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-07-23 17:41:19 +02:00
0e696eb46f Allow navigating from issue to repo (#937)
Allow navigating from issue opend by link to go back to repo

Closes #747

Co-authored-by: qwerty287 <ndev@web.de>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/937
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-07-09 17:36:59 +02:00
2b3b0fbe0f Fix Gitea version check (#945)
Closes #941

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/945
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-06-20 17:26:13 +02:00
f96827488b Hide mark as read button when no notifications are available (#938)
Closes #847

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/938
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-06-17 22:00:33 +02:00
8d0df59bfe Fixing CI (#936)
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/936
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: opyale <opyale@noreply.codeberg.org>
Co-committed-by: opyale <opyale@noreply.codeberg.org>
2021-06-13 19:38:28 +02:00
d567a012d8 Add option to delete branch after pr got merged (#929)
### Describe what your pull request does and which issue you’re targeting
<!-- Create a new issue, if it doesn't exist yet -->
Closes #860
<br><br>

<!-- Make sure you are targeting the "main" branch, pull requests on release branches are only allowed for bug fixes. -->

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/929
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-06-10 18:03:52 +02:00
0fc845e058 Small improvements to About dialog (#927)
As title

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/927
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-06-06 21:15:32 +02:00
b97fa45b18 Move settings arrays to resources (#924)
### Describe what your pull request does and which issue you’re targeting
<!-- Create a new issue, if it doesn't exist yet -->
Closes #920
<br><br>

<!-- Make sure you are targeting the "main" branch, pull requests on release branches are only allowed for bug fixes. -->

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/924
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-06-05 16:07:05 +02:00
d458d60122 Add ScrollViews to DeepLink view (#923)
### Describe what your pull request does and which issue you’re targeting
<!-- Create a new issue, if it doesn't exist yet -->
Closes #921
<br><br>

<!-- Make sure you are targeting the "main" branch, pull requests on release branches are only allowed for bug fixes. -->

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/923
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-05-30 20:57:02 +02:00
881aad5f2d New About App dialog, improvements and fixes (#922)
Possible fix for #917

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/922
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-05-30 19:28:14 +02:00
547e7c705d Use language provided by system (#914)
Pr tries to implement support for usage of system language.

Currently work in progress.

- [x] add option to use system language
- [x] use this by default
- [x] fix other usages of db value "locale"
- [X] fix usages of `Locale.getDefault()` (except [here](https://codeberg.org/gitnex/GitNex/src/branch/main/app/src/main/java/org/mian/gitnex/helpers/ssl/MemorizingTrustManager.java#L429))
- [ ] get language list programmaticaly
- [X] localize language names (related to #101)
- [X] move languages list to ~~Hashmap~~ TreeMap (it seems that HashMaps sort everything in a random order)

I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).
<br>
Fixes #899

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/914
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-05-29 18:21:48 +02:00
cc70fe9a68 Make markdown links clickable (#916)
Pr makes links in markdown clickable.

Closes #797
<br><br>

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/916
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-05-28 21:23:07 +02:00
3b3b0ada2f Public organizations (#906)
Closes #903

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: opyale <opyale@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/906
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-05-25 22:39:06 +02:00
a9f1010add Improve reply comment title (#912)
Closes #910

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/912
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-05-25 21:26:21 +02:00
c8872ade9f Fix typo (#911)
Fixes "Crodwin" typo

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/911
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-05-25 14:35:30 +02:00
960eaa1cf9 Fix missing docker image. (#909)
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/909
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: opyale <opyale@noreply.codeberg.org>
Co-committed-by: opyale <opyale@noreply.codeberg.org>
2021-05-24 14:42:08 +02:00
224ead33bf Fix going back from about fragment (#908)
### Describe what your pull request does and which issue you’re targeting
This PR fixes the problem that you can't go back from the "About" section in the settings and it changes the action bar behaviour of the about fragment to keep the design consistent (see below).

The activity action bar is hidden [here](82ffeefdc4/app/src/main/java/org/mian/gitnex/fragments/AboutFragment.java (L35)), as the about fragment uses it's own (in my implementation) to keep the design consistent (currently, all sections of the settings are own activitys and their action bar has a close button, except the about section). If you don't like this, I can remove it, but currently, it doesn't look nice integrated.

Closes #905

- [X] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [X] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [X] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/908
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-05-23 22:29:11 +02:00
1dd615fcae Moving to 'main' branch (#902)
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/902
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: opyale <opyale@noreply.codeberg.org>
Co-committed-by: opyale <opyale@noreply.codeberg.org>
2021-05-01 20:30:44 +02:00
8741074906 UI improvements and update translation file (#900)
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/900
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-05-01 00:01:22 +02:00
23b8301fbf Fix repo desc in recyclerview (#896)
fixes and clean up

Use Authorization.get()

minor  fixes

Fix repo desc in recyclerview

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: opyale <opyale@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/896
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-04-15 17:05:56 +02:00
d72f097012 Implement multi-session notification polling and additional improvements/refactors/cleanups/fixes (#875)
Merge branch 'master' of https://codeberg.org/gitnex/GitNex into notifications-performance-improvements

 Conflicts:
	app/src/main/java/org/mian/gitnex/adapters/DraftsAdapter.java
	app/src/main/java/org/mian/gitnex/adapters/NotificationsAdapter.java
	app/src/main/java/org/mian/gitnex/adapters/UserAccountsAdapter.java
	app/src/main/java/org/mian/gitnex/adapters/UserAccountsNavAdapter.java
	app/src/main/res/layout/bottom_sheet_repository_in_list.xml
	app/src/main/res/layout/list_files.xml

Merge branch 'master' into notifications-performance-improvements

Merge branch 'master' into notifications-performance-improvements

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into notifications-performance-improvements

 Conflicts:
	app/src/main/res/values-it/strings.xml

Add ripple effect to buttons.

Run syntax highlighting on separate thread. (#859)

Initial commit.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/875
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-04-13 20:56:50 +02:00
9d3cd49d23 New UI for multiple screens (#894)
clean up

Another round of ui improvements and some refactors

Minor improvements.

Hide user accounts frame while list is loading

Remove unnecessary attribute

Minor improvements.

Define avatar size in lists globally.

Improvemnts to some ui elements

Improve layout of organizations and repositories.

Update the UI across most of the screens

Refactor org UI

clean up repo layout

Add archived msg instead of label

Redesign repos UI

Move archived to repo detail screen

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: opyale <opyale@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/894
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-04-13 16:19:42 +02:00
27a4bab73c Remove "Android PdfViewer" library (#893)
Remove "Android PdfViewer" library

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/893
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-04-10 21:16:07 +02:00
69a5f00771 Add private icon in repo detail toolbar, switch to if by gradle lint (#892)
Hide repoTypeToolbar by default.

Merge branch 'master' into add-repo-status-icon

Add private icon in repo detail toolbar, switch to if by gradle lint

Co-authored-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/892
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-04-10 20:29:21 +02:00
8104889bf6 Improve markdown rendering performance (#890)
Use object pooling with up to 45 threads for improved parallelization in markdown rendering.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/890
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-04-10 19:54:05 +02:00
bd3e6ff20a [Frontport] Tr updates (#871)
Tr updates

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/871
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-04-01 12:02:35 +02:00
a384128c8f Launch Toasts on UI thread. (#868)
Launch Toasts on UI thread.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/868
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-03-31 19:36:11 +02:00
4b140f3195 Fixing crash on ProfileFragment (#865)
Fixing crash on ProfileFragment

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/865
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-03-31 18:36:47 +02:00
4ccc66b04e Fix lock icon for repos (#864)
Fix lock icon for repos

Fix layout

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/864
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-03-31 18:28:18 +02:00
7c6247782b [Frontport] Fix Acra and workmanager, update gradle (#856)
Move acra to application

[Frontport] Fix Acra and workmanager errors, update gradle

Fix ACRA and workmanager errors

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/856
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-03-30 16:31:39 +02:00
3e5fca4f52 Fall back to plain text if syntax highlighting fails. (#854)
[HotFix] Fall back to plain text if syntax highlighting fails.

upstream issue: https://github.com/noties/Prism4j/issues/8

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/854
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-03-30 00:31:26 +02:00
a848cabcda Release 3.5.0 (#850)
Release 3.5.0

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/850
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-03-21 20:40:41 +01:00
0b8d8618ed Update French (#849)
Update French

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/849
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: 6543 <6543@noreply.codeberg.org>
Co-Committed-By: 6543 <6543@noreply.codeberg.org>
2021-03-21 20:14:01 +01:00
62ce30db23 Crowdin 2020-03-21 (#848)
Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/848
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: 6543 <6543@noreply.codeberg.org>
Co-Committed-By: 6543 <6543@noreply.codeberg.org>
2021-03-21 19:57:34 +01:00
dc29a31e63 Replacing highlightJS with custom view due to performance issues and high file sizes. (#837)
Fixing crash and minor improvements.

Add ".properties" and ".ini" formats.

Increase surface area of files list item.

Fixing issue where some source code is not visible.

Replacing highlightJS with custom view due to performance issues and high file sizes.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/837
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-03-21 19:26:28 +01:00
98cf1a1976 Improve file type handling. (#841)
Removing file size selection dialog in favor of hardcoded value.

Adding warning to file size picker and minor improvements.

Bump dependencies and gradle

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition

Improving credits, adding symlink and submodule icons to FilesAdapter and removing unused libraries.

Minor improvements and bug fixes.

Add true progress indication routine for copying streams.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition

Performance and memory usage improvements

Notification improvements

Renaming StaticGlobalVariables to Constants

Overall improvements and fixes.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition

Add additional image formats.

Adding audio and video categories.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition

Improve file type handling.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/841
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-03-21 16:56:54 +01:00
ef3108db14 Crowdin 2021-03-18 (#845)
Crowdin 2021-03-18

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/845
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: 6543 <6543@noreply.codeberg.org>
Co-Committed-By: 6543 <6543@noreply.codeberg.org>
2021-03-18 11:48:54 +01:00
f1c88921bc Update readme (#844)
add line for used trademarks

update readme

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/844
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-03-10 13:05:07 +01:00
fb0bd0299c Disable cancel repo settings dialogs (#843)
Merge branch 'master' into disable-dialog-close-repo-settings

Disable cancel repo settings dialogs

Co-authored-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/843
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-03-09 22:21:42 +01:00
c353275ab8 Biometric support (#820)
Minor improvements.

Merge branch 'master' into biometric-support

# Conflicts:
#	app/src/main/res/values/strings.xml

Merge branch 'master' into biometric-support

Merge branch 'master' into biometric-support

UI transition improvements

check for older version(android 6+), support for android 10 and below

Fix material lib builds with new version

Merge branch 'biometric-support' of codeberg.org:gitnex/GitNex into biometric-support

Merge branch 'master' into biometric-support

# Conflicts:
#	app/src/main/java/org/mian/gitnex/activities/BaseActivity.java
#	app/src/main/res/values/strings.xml

Merge branch 'master' into biometric-support

Merge branch 'master' into biometric-support

Merge branch 'master' into biometric-support

set status to false

Merge branch 'master' into biometric-support

check for bimetric status on device

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into biometric-support

close app if back button or cancel is clicked

Enable/disable and show biometric auth dialog

Layout

Co-authored-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: 6543 <6543@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/820
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-03-09 22:15:42 +01:00
328dbaa01c Copy user id to clipboard (#840)
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-03-05 06:24:48 +01:00
ff915f1813 Make singletons threadsafe. (#838)
Merge branch 'master' into threadsafe-singletons

Make singletons threadsafe.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/838
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-03-03 15:10:23 +01:00
77e39952c1 Crowdin 2021-03-03 (#839)
Crowdin 2021-03-03

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/839
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: 6543 <6543@noreply.codeberg.org>
Co-Committed-By: 6543 <6543@noreply.codeberg.org>
2021-03-03 10:27:49 +01:00
afffb7c15a Switch to proper account for popular instances and other ui improvements (#836)
* improve navigation via keyboard

* switch to proper account for popular instances

* ui improvements

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/836
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-02-25 00:22:11 +01:00
47d6c68410 Improve files ui and bug fix encoding in names (#834)
Minor UI and performance improvements.

use one image and remove relativelayout

Fix html codes in name, fix org fragment tab count to load Members

Improve files ui

Co-authored-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/834
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-02-21 23:15:46 +01:00
57ce453661 Fixing bug where path separators would be URL encoded. (#832)
Merge branch 'master' of https://codeberg.org/gitnex/GitNex into fix-path-encoding-issues

Fixing bug where path separators would be URL encoded.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/832
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-02-17 14:51:20 +01:00
d8a14105c9 Fixing and improving scaling of images, improving performance by doing work that has to be done once only once and using different terminology. (#831)
remove unknown case for editing

Improve var names and code formatting

Minor improvements.

Restoring ACRA functionality.

Fixing and improving scaling of images, improving performance by doing work that has to be done once only once and using different terminology.

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/831
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-02-13 20:31:38 +01:00
711711274e Fix canvas too large crash (#830)
fix crash by scaling the image resolution

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/830
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-02-12 23:16:29 +01:00
44b8ad8d1c Add crowdin-cli config template (#827)
Add example crowdin Config

„crowdin.yml“ ändern

now able to upload new strings.xml file

add crowdin config (without API key)

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: 6543 <6543@noreply@gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/827
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: 6543 <6543@noreply.codeberg.org>
Co-Committed-By: 6543 <6543@noreply.codeberg.org>
2021-02-12 10:30:02 +01:00
fc49e29703 Crowdin 2021-02-11 (#828)
Crowdin 2021-02-11

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/828
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: 6543 <6543@noreply.codeberg.org>
Co-Committed-By: 6543 <6543@noreply.codeberg.org>
2021-02-12 10:29:04 +01:00
7f8595defc Fixing theme issues in RepoStargazersActivity. (#825)
Merge branch 'master' into fixing-theme-on-stargazers

Fixing theme issues in RepoStargazersActivity.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/825
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-02-11 14:40:06 +01:00
eb858f3535 Moving ApiInterface, WebInterface and models to different repository. (#824)
Gradle v6.8.2

Use release instead of commit hash.

Moving ApiInterface, WebInterface and models to different repository.

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/824
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-02-11 11:23:35 +01:00
29653cade2 Calling overloaded method first. (#823)
Calling overloaded method first.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/823
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-02-09 13:51:13 +01:00
d72cd57cd7 Cron tasks (#817)
* Run task

* Add info popup dialog for details

* List cron tasks

* Add cron to admin screen

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/817
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-02-04 04:47:00 +01:00
cb241d80f3 Fix crash on creating new file (#819)
Allow multi line text in desc inputs

Minor improvements.

Improving the selection of branches.

Default to first branch in spinner.

Minor improvements.

fix crash on creating new file

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: opyale <opyale@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/819
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-02-01 19:13:48 +01:00
3c381f372e Add execution permissions for script. (#815)
Add execution permissions for script.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/815
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-01-27 10:00:18 +01:00
2398995928 Update nextcloud image. (#814)
Update nextcloud image.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/814
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-01-27 05:01:56 +01:00
7faf800d02 Changing docker image. (#813)
Changing docker image.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/813
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-01-27 00:24:50 +01:00
d0c06a65f4 Add tool to set commit status. (#812)
Add tool to set commit status.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/812
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-01-26 23:21:47 +01:00
20b203c4ad Render emoji in issue/pr titles, commit msg and markdown files (#805)
Merge branch 'master' into render-emoji-in-titles

Merge branch 'master' into render-emoji-in-titles

Merge branch 'master' into render-emoji-in-titles

# Conflicts:
#	app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java
#	app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java
#	app/src/main/java/org/mian/gitnex/adapters/PullRequestsAdapter.java

Render emoji in issue/pr titles, commit msg and markdown files

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/805
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-01-26 18:53:59 +01:00
b02c87b143 Support hx and ts files (#811)
Support hx and ts files

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/811
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-01-26 18:48:24 +01:00
093204df43 Fixing layout issues and crashes. (#810)
Fixing layout issues and crashes.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/810
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-01-26 18:43:25 +01:00
a26737e510 Rewriting deprecated code and adding view bindings to all fragments and activities. (#809)
Remove jetbrain import

Merge branch 'master' into deprecations

View bindings #3

View bindings #2

View bindings #1

Rewriting deprecated code.

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/809
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-01-26 16:10:31 +01:00
371649b8ca Adding ProGuard rules to improve performance on low-spec devices. (#808)
Fixing failing build.

Bumping dependencies.

Adding ProGuard rules to improve performance on low-spec devices.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/808
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-01-26 15:08:55 +01:00
8c62ecadbc Fix crash for offline mode org labels (#804)
Merge branch 'master' into fix-offline-org-labels

Fix crash for offline mode org labels

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/804
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-01-14 18:42:35 +01:00
b75bf84d43 Rewriting deprecated code and improving offline mode. (#800)
Moving UI-related code to message queue of main thread.

Removing NetworkObserver in favor of NetworkStatusObserver

Some fixes.

Removing deprecated PreferenceManager.

Fixing crash.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into fix-performance-regression

 Conflicts:
	app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java

Rewriting deprecated code.

Improving degraded performance due to unnecessary object allocation.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/800
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-01-14 17:33:50 +01:00
5d2bb02b2d Improving degraded performance due to unnecessary object allocation. (#799)
Improving degraded performance due to unnecessary object allocation.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/799
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
2021-01-01 18:30:30 +01:00
fef1597522 dev-3.5.0 (#798)
fix typo

start dev of 3.5.0

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/798
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2021-01-01 12:57:16 +01:00
1f9a3eb85d Crowdin 2020-12-31 (#795)
CI.restart()

Crowdin 2020-12-31

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/795
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: 6543 <6543@noreply.codeberg.org>
Co-Committed-By: 6543 <6543@noreply.codeberg.org>
2020-12-31 16:55:13 +01:00
a51ba4f2a8 Fix offline mode (#794)
Closes #790

update libs

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/794
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org>
Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
2020-12-31 15:38:18 +01:00
4c4a7376cb Uppdate Supported Gitea Version Range (#793)
Uppdate Supported Gitea Versins

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/793
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: 6543 <6543@noreply.codeberg.org>
Co-Committed-By: 6543 <6543@noreply.codeberg.org>
2020-12-15 08:57:47 +01:00
bbbcb56b98 Organization labels (#771)
List, Create, Edit & Delete OrgLabels

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/771
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-11-30 23:20:14 +01:00
b871a1fb22 Removing left-over space in case no reactions are available (#782)
update gradle

Removing left-over space in case no reactions are available.

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: 6543 <6543@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/782
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-11-30 00:26:01 +01:00
f2bc81210c Cap sentence start letters where necessary in input fields (#786)
Cap sentence start letters where necessary in input fields

Co-authored-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/786
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-11-29 23:41:44 +01:00
a6e97a1b36 Add new theme - Pitch Black (#787)
update drawables

Add new theme - Pitch Black

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/787
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-11-29 22:51:35 +01:00
2ebcdf9186 Kick start dev of 3.4.0 (#781)
Kick start development of 3.4.0

Release 3.3.0

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/781
2020-11-18 08:25:34 +01:00
272fc78df9 [Frontport] Fix add new account (#779)
Fix add new account

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/779
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-11-17 19:56:16 +01:00
3aa819f3ef [Frontport] Fix date and minor ui improvements (#774)
Fix date and minor ui improvements

Co-authored-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/774
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-11-17 05:40:58 +01:00
e9fa2984a1 Update Translations 2020-11-16 (#775)
Update Translations 2020-11-16

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/775
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-11-16 14:13:43 +01:00
240cdf5701 Fix pr pagination (#770)
links improvement

Fix button alignment in polling delay popup

Fix pr pagination

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/770
2020-11-13 16:04:43 +01:00
a170c10e43 Improve deeplinks (#769)
Change to mainIntent

Add commit to deep links

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/769
2020-11-13 16:04:14 +01:00
d11da92fc4 Fixing missing emotes. (#768)
switch to tagged version (v5.1.2)

Using JitPack for artifact instead.

Fixing missing emotes.

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/768
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-11-08 23:57:33 +01:00
3b53111981 3.3.0 rc3 release (#766)
3.3.0 rc3 release

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/766
2020-11-08 20:09:29 +01:00
ade7b797f1 Add Issue/Comment Reactions (#557)
Minor performance improvements.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into issue-reactions

Improving color of selected elements.

First, fully working implementation of reactions.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into issue-reactions

 Conflicts:
	app/src/main/res/layout/bottom_sheet_issue_comments.xml
	app/src/main/res/layout/list_issue_comments.xml

(Hopefully) fixing merge issues.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into issue-reactions

 Conflicts:
	app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java
	app/src/main/res/layout/activity_issue_detail.xml
	app/src/main/res/layout/bottom_sheet_issue_comments.xml
	app/src/main/res/layout/bottom_sheet_single_issue.xml
	app/src/main/res/values/colors.xml

Moving reactions below time frame on comments.

Merge branch 'master' into layout-reactions

Add IssueReactions

Merge remote-tracking branch 'origin/layout-reactions' into layout-reactions

Merge branch 'master' of https://gitea.com/gitnex/GitNex into layout-reactions

Merge branch 'master' into layout-reactions

Applying to pulls and issues.

Merge branch 'master' of https://gitea.com/gitnex/GitNex into layout-reactions

Providing external layouts.

Some improvements.

Adding comment emote indications.

Adding circle around emotes.

Adding some padding.

First tests.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: 6543 <6543@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/557
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-11-08 19:58:47 +01:00
f97f668363 Improve nav drawer lag (#765)
Improve drawer nav lagginess

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/765
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-11-06 02:09:34 +01:00
639cf51027 Org level labels in issue labels (#763)
Adding null checks.

Minor cleanups.

Merge branch 'master' into org-labels-in-issue

Fix repo size

Add new instances

Merge branch 'master' into org-labels-in-issue

Add org level labels to issue labels

Co-authored-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/763
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-11-05 13:10:17 +01:00
a92da6a6d4 Improve notifications (#764)
Moving translation.

Adding option to enable/disable notifications.

Fix typos

Improve notifications

Co-authored-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/764
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-11-03 20:14:24 +01:00
87379ae0b2 Refactor deeplinks (#762)
Minor improvements.

refactor deeplinks

Add popular instances taken from #758

Co-authored-by: opyale <opyale@noreply.codeberg.org>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/762
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-11-02 18:01:06 +01:00
43166237ee Adding link to CI. (#761)
Adding link to CI.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/761
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-11-02 16:25:45 +01:00
a3bd5c2af2 Increasing performance, fixing bugs and adding syntax highlighting. (#755)
Merge branch 'performance-highlight-refactor' of https://codeberg.org/opyale/GitNex into performance-highlight-refactor

Fixing theme recognition.

Merge branch 'master' into performance-highlight-refactor

Merge commit 'refs/pull/755/head' of codeberg.org:gitnex/GitNex into performance-highlight-refactor

Add new field issueType to db

Improving theme recognition.

Fixing alignment of menu button.

Fixing cut off text.

Merge commit 'refs/pull/755/head' of codeberg.org:gitnex/GitNex into performance-highlight-refactor

Fixing crash.

Refactoring activities.

Improving drafts.

Calculating density for avatars.

Improving drafts.

Calculating density for avatars.

Increasing size of avatar.

Decreasing size of avatar.

Restoring DeepLinksActivity

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into performance-highlight-refactor

 Conflicts:
	app/src/main/java/org/mian/gitnex/adapters/IssueCommentsAdapter.java

Initial commit.

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/755
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-11-02 16:17:00 +01:00
0f5858f292 Compress PNG (#759)
Compress PNG

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/759
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-11-02 16:01:59 +01:00
dcec158076 Remove liberapay (#754)
remove about screen

remove liberapay

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/754
2020-10-30 16:12:13 +01:00
63d3c95501 Release 3.3.0 rc2 (#753)
Release 3.3.0 rc2

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/753
2020-10-30 08:07:23 +01:00
f111f7f2df Fix scrolling issue for textareas (#752)
Add info msg for merge 405

Fix scrolling issue for textareas

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/752
2020-10-30 08:00:52 +01:00
5807d11e8c Fixing scrolling. (#751)
Fixing scrolling.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/751
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-10-29 18:37:06 +01:00
4a9bde8731 Improving templates. (#746)
Additional improvements.

Merge branch 'master' into improving-templates

Improving templates.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/746
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-10-29 17:24:19 +01:00
f64e23dcc1 Enhance settings screen and make it translation ready (#735)
Merge branch 'master' into enhance-settings-screen

# Conflicts:
#	app/src/main/java/org/mian/gitnex/activities/FileViewActivity.java

Cleanup and refactor of activities

Fix bottomsheet

enhance code blocks and refactors

Move home screen to general, make it ready for translation

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/735
2020-10-29 14:13:19 +01:00
6a9144435e Layout and UI improvements (#738)
Layout and UI improvements

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/738
2020-10-29 13:53:03 +01:00
3c7b505b5b Fix view recycling issue (#742)
Fix view issue

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/742
2020-10-29 13:52:40 +01:00
2064c40c7d Remove deprecated startActivity for file download (#737)
Remove deprecated startActivity for file download

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/737
2020-10-29 13:51:52 +01:00
65c0ecaad1 Fix deep links (#743)
Fix opening links

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/743
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-10-29 00:21:47 +01:00
99925621f1 Fix apk download image (#740)
Fix apk download image

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/740
2020-10-28 13:36:07 +01:00
508 changed files with 20717 additions and 19802 deletions

View File

@ -15,8 +15,8 @@ steps:
image: zosiab/eclint:latest
depends_on: [ clone ]
commands:
- git pull origin master
- eclint check $(git diff --name-only origin/master)
- git pull origin main
- eclint check $(git diff --name-only origin/main)
# This may be used in the future, because it makes of intellij's native code inspection/formatting capabilities.
# Additional information: https://www.jetbrains.com/help/idea/command-line-formatter.html
@ -54,7 +54,7 @@ trigger:
event:
- push
branch:
- master
- main
---
kind: pipeline
@ -101,4 +101,4 @@ trigger:
event:
- push
branch:
- master
- main

View File

@ -1,33 +1,37 @@
## # What do you want to address?
(This step is required; examples are shown below)
<!-- This step is required; examples are shown below -->
- [ ] Bug
- [ ] Feature
- [ ] Suggestion
## # Describe your matter briefly
(This step is required)
<!-- This step is required. -->
<br><br>
##### What did you expect? (Useful when addressing bugs)
##### What did you expect? <!-- Useful when addressing bugs -->
---
_(This step is optional)_
<!-- This step is optional. -->
<br><br>
##### Some additional details (Useful, when we are trying to reproduce a bug)
##### Some additional details <!-- Useful, when we are trying to reproduce a bug -->
---
_(This step is optional; an example is shown below)_
<!-- This step is optional; an example is shown below -->
* The version of **Gitea** you are using:
* The version of **GitNex** you are using:
* Source of installation(Google play, F-droid, APK):
* Phone **OS** version and model:
* The type of certificate you are using (self-signed, signed):
* Source of installation (Play Store, F-Droid, APK):
* Current android version and phone model/manufacturer:
* The type of certificate your instance is using (self-signed, signed):
* How you used to log in (via password or token):
<br>
##### We would appreciate some screenshots or stacktrace's, but this is also not required.
---
_(Screenshots and stacktrace's can go here)_
<!-- Screenshots and stacktrace's can go here. -->
<br><br>
- [ ] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
<br>
#### Thank you for your time.

View File

@ -1,8 +1,9 @@
Please check the following:
### Describe what your pull request does and which issue youre targeting
<!-- Create a new issue, if it doesn't exist yet -->
<br><br>
1. Make sure you are targeting the `master` branch, pull requests on release branches are only allowed for bug fixes.
2. Read contributing guidelines: [CONTRIBUTING.md](https://gitea.com/GitNex/GitNex/src/branch/master/CONTRIBUTING.md)
3. Please follow the [Code-Standards](https://gitea.com/gitnex/GitNex/wiki/Code-Standards)
4. Describe what your pull request does and which issue youre targeting (create one if does not exist)
<!-- Make sure you are targeting the "main" branch, pull requests on release branches are only allowed for bug fixes. -->
**You MUST delete the content above including this line before posting, otherwise your pull request will be invalid.**
- [ ] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
- [ ] I'm following the code standards as defined [here](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards).
- [ ] By submitting this pull request, I permit GitNex to license my work under the [GNU General Public License v3](https://codeberg.org/GitNex/GitNex/src/branch/main/LICENSE).

3
.gitignore vendored
View File

@ -195,3 +195,6 @@ crowdin.yml
!/gradle/wrapper/gradle-wrapper.jar
# End of https://www.gitignore.io/api/android,androidstudio
# Crowdin Config
crowdin.yml

View File

@ -1,23 +1,26 @@
stages:
- test
- build
- sign
- publish
test:
image: nextcloudci/android:android-49
stage: test
on_setup:
image: curlimages/curl:7.77.0
stage: .pre
only:
- master
- main
- tags
variables:
INSTANCE: "https://codeberg.org"
MAIN_REPO: gitnex/GitNex
STATE: pending
script:
- ./gradlew test
- ./scripts/add-commit-status.sh
build:
image: nextcloudci/android:android-49
image: nextcloudci/android:android-54
stage: build
only:
- master
- main
- tags
script:
- ./gradlew assembleFreeRelease
@ -27,10 +30,10 @@ build:
expire_in: 15 minutes
sign:
image: nextcloudci/android:android-49
image: nextcloudci/android:android-54
stage: sign
only:
- master
- main
- tags
variables:
OUTPUT: "signed.apk"
@ -44,10 +47,10 @@ sign:
expire_in: 15 minutes
latest:
image: tutum/curl
image: curlimages/curl:7.77.0
stage: publish
only:
- master
- main
- tags
variables:
WEBDAV_USERNAME: "GitNexBot"
@ -57,7 +60,7 @@ latest:
- curl -T "$PLUGIN_FILE" -u "$WEBDAV_USERNAME":"$WEBDAV_PASSWORD" "$PLUGIN_DESTINATION"
release:
image: tutum/curl
image: curlimages/curl:7.77.0
stage: publish
only:
- tags
@ -67,3 +70,31 @@ release:
script:
- "[[ $CI_COMMIT_REF_NAME == *'-rc'* ]] && echo 'Upload blocked. Build seems to be a release candidate.' && exit 0"
- curl -T "$PLUGIN_FILE" -u "$WEBDAV_USERNAME":"$WEBDAV_PASSWORD" 'https://cloud.swatian.com/remote.php/dav/files/GitNexBot/gitnex/releases/'"$CI_COMMIT_REF_NAME"'.apk'
on_success:
image: curlimages/curl:7.77.0
stage: .post
only:
- main
- tags
variables:
INSTANCE: "https://codeberg.org"
MAIN_REPO: gitnex/GitNex
STATE: success
script:
- ./scripts/add-commit-status.sh
when: on_success
on_failure:
image: curlimages/curl:7.77.0
stage: .post
only:
- main
- tags
variables:
INSTANCE: "https://codeberg.org"
MAIN_REPO: gitnex/GitNex
STATE: failure
script:
- ./scripts/add-commit-status.sh
when: on_failure

View File

@ -19,9 +19,18 @@
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" withSubpackages="false" static="false" />
<package name="kotlinx.android.synthetic" withSubpackages="true" static="false" />
<package name="io.ktor" withSubpackages="true" static="false" />
<package name="java.util" alias="false" withSubpackages="false" />
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
<package name="io.ktor" alias="false" withSubpackages="true" />
</value>
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
</JetCodeStyleSettings>
@ -171,4 +180,4 @@
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>
</component>

View File

@ -2,26 +2,35 @@
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 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.
### General
> **Be polite and gentle while commenting or creating new issues to maintain a healthy environment in which __everyone__ is able to feel comfortable.**
<br>
Please ask if you are not sure about the scope of work to be submitted to avoid waste of time spent on the work.
### Issues and Reports
Before creating an issue please take a moment and search the repository issues(open/closed) to avoid duplicate issues either it's a bug or feature.
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.<br><br>
**Note:** Please contact the project directly via [email](mailto:gitnex@swatian.com) if have to share sensitive and security related details.
<br>
**Code Standards**
### Pull Requests
Patches, enhancements and 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.** (Submit an issue, __before__ submitting a PR)
**Code Standards**<br><br>
Please follow the code standards, this will help other developers to understand your code too.
It also helps maintaining the code afterwards.
It is documented in the Wiki: [Code-Standards](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards)
**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.
**How to submit a PR (Pull Request)**
1. Fork this repository.
2. Clone the forked repository from your namespace to your local machine.
3. Create a new branch and work on your feature, enhancement or patch.
4. Push your commits to your forked version.
5. You can now create a PR using the web interface against **main** branch.
**IMPORTANT:** By submitting PR, you agree to allow GitNex to license your work under the same license as that used by GitNex.
For more information, click [here](http://makeapullrequest.com/).
## Issues and Reports
*1st of please be polite and gentle while commenting or creating new issue to maintain a healthy environment.*
Before creating an issue please take a moment and search the repository issues(open/closed) to avoid duplicate issues either it's a bug or feature.
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.
**IMPORTANT:** By submitting PR, you agree to allow GitNex to license your work under the same license as that used by GitNex.

View File

@ -1,17 +1,17 @@
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) ![Pipeline status](https://img.shields.io/gitlab/pipeline/opyale/gitnex/master) [![Release](https://img.shields.io/badge/dynamic/json.svg?label=release&url=https://codeberg.org/api/v1/repos/gitnex/GitNex/releases&query=$[0].tag_name)](https://codeberg.org/gitnex/GitNex/releases) [![Crowdin](https://badges.crowdin.net/gitnex/localized.svg)](https://crowdin.com/project/gitnex) [![Join the Discord chat at https://discord.gg/FbSS4rf](https://img.shields.io/discord/632219664587685908.svg)](https://discord.gg/FbSS4rf)
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![Pipeline status](https://img.shields.io/gitlab/pipeline/opyale/gitnex/main)](https://gitlab.com/opyale/gitnex/-/pipelines) [![Release](https://img.shields.io/badge/dynamic/json.svg?label=release&url=https://codeberg.org/api/v1/repos/gitnex/GitNex/releases&query=$[0].tag_name)](https://codeberg.org/gitnex/GitNex/releases) [![Crowdin](https://badges.crowdin.net/gitnex/localized.svg)](https://crowdin.com/project/gitnex) [![Join the Discord chat at https://discord.gg/FbSS4rf](https://img.shields.io/discord/632219664587685908.svg)](https://discord.gg/FbSS4rf)
[<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)
[<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)
# GitNex - Android client for Gitea
GitNex is a free/paid, open-source Android client for Git repository management tool Gitea. Gitea is a community managed fork of Gogs, lightweight code hosting solution written in Go.
GitNex is licensed under GPLv3 License. See the LICENSE file for the full license text. No trackers are used and source code is available here for anyone to audit.
GitNex is licensed under GPLv3 License. See the LICENSE file for the full license text. **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.pro)
[<img alt='Download builds and releases' src='https://codeberg.org/gitnex/GitNex/src/branch/master/assets/apk-badge.png' height="82"/>](https://cloud.swatian.com/s/DN7E5xxtaw4fRbE)
[<img alt='Download builds and releases' src='https://codeberg.org/gitnex/GitNex/raw/branch/main/assets/apk-badge.png' height="82"/>](https://cloud.swatian.com/s/DN7E5xxtaw4fRbE)
## Note about Gitea version
Please make sure that you are on latest stable release or later for better app experience.
@ -37,7 +37,7 @@ Option 2 - Open terminal(Linux) and cd to the project dir. Run `./gradlew assemb
- [MANY MORE](https://codeberg.org/gitnex/GitNex/wiki/Features)
## Contributing
[CONTRIBUTING](https://codeberg.org/gitnex/GitNex/src/branch/master/CONTRIBUTING.md)
[CONTRIBUTING](https://codeberg.org/gitnex/GitNex/src/branch/main/CONTRIBUTING.md)
## Translation
Help us translate GitNex to your native language.
@ -48,13 +48,9 @@ We use [Crowdin](https://crowdin.com/project/gitnex) for translation. If your la
## Screenshots:
<img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/001.png" alt="001.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/002.png" alt="002.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/003.png" alt="003.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/004.png" alt="004.png" width="200"/>
<img src="https://codeberg.org/gitnex/GitNex/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/001.png" alt="001.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/002.png" alt="002.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/003.png" alt="003.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/004.png" alt="004.png" width="200"/>
---|---|---|---
<img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/005.png" alt="005.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/006.png" alt="006.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/007.png" alt="007.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/008.png" alt="008.png" width="200"/>
## FAQ
[Faq](https://codeberg.org/gitnex/GitNex/wiki/FAQ)
<img src="https://codeberg.org/gitnex/GitNex/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/005.png" alt="005.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/006.png" alt="006.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/007.png" alt="007.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/008.png" alt="008.png" width="200"/>
## Links
[Website](https://gitnex.com)
@ -65,28 +61,39 @@ We use [Crowdin](https://crowdin.com/project/gitnex) for translation. If your la
[Troubleshoot Guide](https://codeberg.org/gitnex/GitNex/wiki/Troubleshoot-Guide)
[Faq](https://codeberg.org/gitnex/GitNex/wiki/FAQ)
[Release Blog](https://gitnex.codeberg.page)
## Thanks
Thanks to all the open source libraries, contributors and donators.
#### Open source libraries
- Retrofit
- Gson
- Okhttp
- Picasso
- Markwon
- Prettytime
- Amulyakhare/textdrawable
- Vdurmont/emoji-java
- Pes/materialcolorpicker
- HamidrezaAmz/BreadcrumbsView
- Chrisbanes/PhotoView
- Pddstudio/highlightjs-android
- Apache/commons-io
- Caverock/androidsvg
- Droidsonroids.gif/android-gif-drawable
- Barteksc/androidPdfViewer
- Ge0rg/memorizingTrustManager
- Dimezis/blurView
- Mikaelhg/urlbuilder
- [square/retrofit](https://github.com/square/retrofit)
- [google/gson](https://github.com/google/gson)
- [square/okhttp](https://github.com/square/okhttp)
- [square/picasso](https://github.com/square/picasso)
- [wasabeef/picasso-transformations](https://github.com/wasabeef/picasso-transformations)
- [cats-oss/android-gpuimage](https://github.com/cats-oss/android-gpuimage)
- [noties/Markwon](https://github.com/noties/Markwon)
- [noties/Prism4j](https://github.com/noties/Prism4j)
- [ocpsoft/prettytime](https://github.com/ocpsoft/prettytime)
- [amulyakhare/TextDrawable](https://github.com/amulyakhare/TextDrawable)
- [vdurmont/emoji-java](https://github.com/vdurmont/emoji-java)
- [Pes8/android-material-color-picker-dialog](https://github.com/Pes8/android-material-color-picker-dialog)
- [HamidrezaAmz/BreadcrumbsView](https://github.com/HamidrezaAmz/BreadcrumbsView)
- [Baseflow/PhotoView](https://github.com/Baseflow/PhotoView)
- [apache/commons](https://github.com/apache/commons-io)
- [ge0rg/MemorizingTrustManager](https://github.com/ge0rg/MemorizingTrustManager)
- [mikaelhg/urlbuilder](https://github.com/mikaelhg/urlbuilder)
- [ACRA/acra](https://github.com/ACRA/acra)
- [chrisvest/stormpot](https://github.com/chrisvest/stormpot)
#### Icon sets
- [feathericons/feather](https://github.com/feathericons/feather)
- [primer/octicons](https://github.com/primer/octicons)
- [google/material-design-icons](https://github.com/google/material-design-icons)
[Follow me on Fediverse - mastodon.social/@mmarif](https://mastodon.social/@mmarif)
*All trademarks and logos are the properties of their respective owners.*

View File

@ -6,8 +6,8 @@ android {
applicationId "org.mian.gitnex"
minSdkVersion 21
targetSdkVersion 30
versionCode 327
versionName "3.3.0-rc1"
versionCode 410
versionName "4.1.0"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@ -24,13 +24,13 @@ android {
}
}
buildFeatures {
viewBinding = true
viewBinding true
}
buildTypes {
release {
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
lintOptions {
@ -38,8 +38,10 @@ android {
abortOnError false
}
compileOptions {
targetCompatibility = "8"
sourceCompatibility = "8"
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig{
vectorDrawables.useSupportLibrary = true
@ -52,30 +54,32 @@ configurations {
}
dependencies {
def lifecycle_version = '2.3.0-beta01'
def markwon_version = '4.6.0'
def work_version = "2.4.0"
def acra = "5.5.0"
def lifecycle_version = '2.3.1'
def markwon_version = '4.6.2'
def work_version = "2.7.0-alpha05"
def acra = "5.7.0"
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'
implementation 'com.google.android.material:material:1.3.0-alpha03'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
implementation 'androidx.appcompat:appcompat:1.4.0-alpha03'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
implementation "com.google.code.gson:gson:2.8.6"
implementation "com.squareup.picasso:picasso:2.71828"
implementation 'jp.wasabeef:picasso-transformations:2.4.0'
implementation 'jp.co.cyberagent.android:gpuimage:2.1.0'
implementation "com.amulyakhare:com.amulyakhare.textdrawable:1.0.1"
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
implementation 'org.ocpsoft.prettytime:prettytime:4.0.6.Final'
implementation "com.vdurmont:emoji-java:5.1.1"
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2'
implementation 'org.ocpsoft.prettytime:prettytime:5.0.0.Final'
implementation "com.pes.materialcolorpicker:library:1.2.5"
implementation "io.noties.markwon:core:$markwon_version"
implementation "io.noties.markwon:ext-latex:$markwon_version"
@ -90,20 +94,24 @@ dependencies {
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 "io.noties.markwon:image-picasso:$markwon_version"
implementation "io.noties:prism4j:2.0.0"
annotationProcessor "io.noties:prism4j-bundler:2.0.0"
implementation "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9"
implementation "commons-io:commons-io:20030203.000550"
implementation 'org.apache.commons:commons-lang3:3.11'
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation "com.github.chrisbanes:PhotoView:2.3.0"
implementation "com.github.barteksc:android-pdf-viewer:3.2.0-beta.1"
implementation "ch.acra:acra-mail:$acra"
implementation "ch.acra:acra-limiter:$acra"
implementation "ch.acra:acra-notification:$acra"
implementation "androidx.room:room-runtime:2.2.5"
annotationProcessor "androidx.room:room-compiler:2.2.5"
implementation 'androidx.room:room-runtime:2.3.0'
annotationProcessor 'androidx.room:room-compiler:2.3.0'
implementation "androidx.work:work-runtime:$work_version"
implementation "com.eightbitlab:blurview:1.6.3"
implementation "io.mikael:urlbuilder:2.0.9"
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
implementation "org.codeberg.gitnex:tea4j:1.0.24"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
implementation 'androidx.biometric:biometric:1.1.0'
implementation 'com.github.chrisvest:stormpot:2.4.2'
}

View File

@ -19,3 +19,5 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-optimizationpasses 30
-allowaccessmodification

View File

@ -6,11 +6,13 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<application
android:name=".core.MainApplication"
android:allowBackup="true"
android:icon="@mipmap/app_logo"
android:label="@string/app_name"
android:label="@string/appName"
android:networkSecurityConfig="@xml/network_security_config"
android:resizeableActivity="true"
android:roundIcon="@mipmap/app_logo_round"
@ -49,7 +51,7 @@
android:name=".activities.CreateNewUserActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.ProfileEmailActivity"
android:name=".activities.MyProfileEmailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AddCollaboratorToRepositoryActivity"
@ -63,7 +65,7 @@
<activity
android:name=".activities.OrganizationDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:label="@string/title_activity_org_detail"
android:label="@string/titleActivityOrgDetail"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.CreateLabelActivity"
@ -74,9 +76,6 @@
<activity
android:name=".activities.CreateMilestoneActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.ReplyToIssueActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.IssueDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
@ -84,12 +83,13 @@
<activity
android:name=".activities.RepoDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:label="@string/title_activity_repo_detail"
android:label="@string/titleActivityRepoDetail"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.MainActivity"
android:theme="@android:style/Theme.NoTitleBar"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation">
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -124,7 +124,7 @@
android:name=".activities.SettingsAppearanceActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsFileViewerActivity"
android:name=".activities.ProfileActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsSecurityActivity"
@ -156,6 +156,13 @@
<activity
android:name=".activities.SettingsGeneralActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsNotificationsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AdminCronTasksActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>
@ -166,13 +173,22 @@
<activity
android:name=".activities.DeepLinksActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:launchMode="singleTask">
android:noHistory="true"
android:launchMode="singleTask"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="*" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="codeberg.org" />
<data android:host="gitea.com" />
<data android:host="try.gitea.io" />
<data android:host="code.obermui.de" />
<data android:host="git.fsfe.org" />
<data android:host="opendev.org" />
</intent-filter>
</activity>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
!function(e){"use strict";function t(){"complete"===document.readyState?n():e.addEventListener("DOMContentLoaded",n)}function n(){try{var e=document.querySelectorAll("code.hljs");for(var t in e)e.hasOwnProperty(t)&&r(e[t])}catch(n){console.error("LineNumbers error: ",n)}}function r(e){if("object"==typeof e){var t=e.parentNode,n=o(t.textContent);if(n>1){for(var r="",c=0;n>c;c++)r+=c+1+"\n";var l=document.createElement("code");l.className="hljs hljs-line-numbers",l.style["float"]="left",l.textContent=r,t.insertBefore(l,e)}}}function o(e){if(0===e.length)return 0;var t=/\r\n|\r|\n/g,n=e.match(t);return n=n?n.length:0,e[e.length-1].match(t)||(n+=1),n}"undefined"==typeof e.hljs?console.error("highlight.js not detected!"):(e.hljs.initLineNumbersOnLoad=t,e.hljs.lineNumbersBlock=r)}(window);

View File

@ -1,66 +0,0 @@
/*
Date: 24 Fev 2015
Author: Pedro Oliveira <kanytu@gmail . com>
*/
.hljs {
color: #a9b7c6;
background: #282b2e;
display: block;
overflow-x: auto;
padding: 0.5em;
}
.hljs-number,
.hljs-literal,
.hljs-symbol,
.hljs-bullet {
color: #6897BB;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-deletion {
color: #cc7832;
}
.hljs-variable,
.hljs-template-variable,
.hljs-link {
color: #629755;
}
.hljs-comment,
.hljs-quote {
color: #808080;
}
.hljs-meta {
color: #bbb529;
}
.hljs-string,
.hljs-attribute,
.hljs-addition {
color: #6A8759;
}
.hljs-section,
.hljs-title,
.hljs-type {
color: #ffc66d;
}
.hljs-name,
.hljs-selector-id,
.hljs-selector-class {
color: #e8bf6a;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

View File

@ -1,87 +0,0 @@
/*
Arduino® Light Theme - Stefania Mellai <s.mellai@arduino.cc>
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
background: #FFFFFF;
}
.hljs,
.hljs-subst {
color: #434f54;
}
.hljs-keyword,
.hljs-attribute,
.hljs-selector-tag,
.hljs-doctag,
.hljs-name {
color: #00979D;
}
.hljs-built_in,
.hljs-literal,
.hljs-bullet,
.hljs-code,
.hljs-addition {
color: #D35400;
}
.hljs-regexp,
.hljs-symbol,
.hljs-variable,
.hljs-template-variable,
.hljs-link,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #00979D;
}
.hljs-type,
.hljs-string,
.hljs-selector-id,
.hljs-selector-class,
.hljs-quote,
.hljs-template-tag,
.hljs-deletion {
color: #005C5F;
}
.hljs-title,
.hljs-section {
color: #880000;
font-weight: bold;
}
.hljs-comment {
color: rgba(149,165,166,.8);
}
.hljs-meta-keyword {
color: #728E00;
}
.hljs-meta {
color: #434f54;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}
.hljs-function {
color: #728E00;
}
.hljs-number {
color: #8A7B52;
}

View File

@ -1,71 +0,0 @@
/*
FAR Style (c) MajestiC <majestic2k@gmail.com>
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
background: #000080;
}
.hljs,
.hljs-subst {
color: #0ff;
}
.hljs-string,
.hljs-attribute,
.hljs-symbol,
.hljs-bullet,
.hljs-built_in,
.hljs-builtin-name,
.hljs-template-tag,
.hljs-template-variable,
.hljs-addition {
color: #ff0;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-section,
.hljs-type,
.hljs-name,
.hljs-selector-id,
.hljs-selector-class,
.hljs-variable {
color: #fff;
}
.hljs-comment,
.hljs-quote,
.hljs-doctag,
.hljs-deletion {
color: #888;
}
.hljs-number,
.hljs-regexp,
.hljs-literal,
.hljs-link {
color: #0f0;
}
.hljs-meta {
color: #008080;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-title,
.hljs-section,
.hljs-name,
.hljs-strong {
font-weight: bold;
}
.hljs-emphasis {
font-style: italic;
}

View File

@ -1,99 +0,0 @@
/*
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
}
.hljs-comment,
.hljs-quote {
color: #998;
font-style: italic;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-subst {
color: #333;
font-weight: bold;
}
.hljs-number,
.hljs-literal,
.hljs-variable,
.hljs-template-variable,
.hljs-tag .hljs-attr {
color: #008080;
}
.hljs-string,
.hljs-doctag {
color: #d14;
}
.hljs-title,
.hljs-section,
.hljs-selector-id {
color: #900;
font-weight: bold;
}
.hljs-subst {
font-weight: normal;
}
.hljs-type,
.hljs-class .hljs-title {
color: #458;
font-weight: bold;
}
.hljs-tag,
.hljs-name,
.hljs-attribute {
color: #000080;
font-weight: normal;
}
.hljs-regexp,
.hljs-link {
color: #009926;
}
.hljs-symbol,
.hljs-bullet {
color: #990073;
}
.hljs-built_in,
.hljs-builtin-name {
color: #0086b3;
}
.hljs-meta {
color: #999;
font-weight: bold;
}
.hljs-deletion {
background: #fdd;
}
.hljs-addition {
background: #dfd;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

View File

@ -1,73 +0,0 @@
/*
IR_Black style (c) Vasily Mikhailitchenko <vaskas@programica.ru>
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
background: #000;
color: #f8f8f8;
}
.hljs-comment,
.hljs-quote,
.hljs-meta {
color: #7c7c7c;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-tag,
.hljs-name {
color: #96cbfe;
}
.hljs-attribute,
.hljs-selector-id {
color: #ffffb6;
}
.hljs-string,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-addition {
color: #a8ff60;
}
.hljs-subst {
color: #daefa3;
}
.hljs-regexp,
.hljs-link {
color: #e9c062;
}
.hljs-title,
.hljs-section,
.hljs-type,
.hljs-doctag {
color: #ffffb6;
}
.hljs-symbol,
.hljs-bullet,
.hljs-variable,
.hljs-template-variable,
.hljs-literal {
color: #c6c5fe;
}
.hljs-number,
.hljs-deletion {
color:#ff73fd;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

View File

@ -1,83 +0,0 @@
/*
Monokai Sublime style. Derived from Monokai by noformnocontent http://nn.mit-license.org/
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
background: #23241f;
}
.hljs,
.hljs-tag,
.hljs-subst {
color: #f8f8f2;
}
.hljs-strong,
.hljs-emphasis {
color: #a8a8a2;
}
.hljs-bullet,
.hljs-quote,
.hljs-number,
.hljs-regexp,
.hljs-literal,
.hljs-link {
color: #ae81ff;
}
.hljs-code,
.hljs-title,
.hljs-section,
.hljs-selector-class {
color: #a6e22e;
}
.hljs-strong {
font-weight: bold;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-name,
.hljs-attr {
color: #f92672;
}
.hljs-symbol,
.hljs-attribute {
color: #66d9ef;
}
.hljs-params,
.hljs-class .hljs-title {
color: #f8f8f2;
}
.hljs-string,
.hljs-type,
.hljs-built_in,
.hljs-builtin-name,
.hljs-selector-id,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-addition,
.hljs-variable,
.hljs-template-variable {
color: #e6db74;
}
.hljs-comment,
.hljs-deletion,
.hljs-meta {
color: #75715e;
}

View File

@ -5,6 +5,8 @@ import android.content.Context;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.Collaborators;
import org.gitnex.tea4j.models.Issues;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.AssigneesListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
@ -12,8 +14,6 @@ import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
@ -24,12 +24,11 @@ import retrofit2.Callback;
public class AssigneesActions {
public static void getCurrentIssueAssignees(Context ctx, String instanceUrl, String loginUid, String instanceToken, String repoOwner, String repoName, int issueIndex, List<String> currentAssignees) {
public static void getCurrentIssueAssignees(Context ctx, String repoOwner, String repoName, int issueIndex, List<String> currentAssignees) {
Call<Issues> callSingleIssueLabels = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex);
.getApiInterface(ctx)
.getIssueByIndex(Authorization.get(ctx), repoOwner, repoName, issueIndex);
callSingleIssueLabels.enqueue(new Callback<Issues>() {
@ -63,14 +62,13 @@ public class AssigneesActions {
});
}
public static void getRepositoryAssignees(Context ctx, String instanceUrl, String instanceToken, String repoOwner, String repoName, List<Collaborators> assigneesList, Dialog dialogAssignees, AssigneesListAdapter assigneesAdapter, CustomAssigneesSelectionDialogBinding assigneesBinding) {
public static void getRepositoryAssignees(Context ctx, String repoOwner, String repoName, List<Collaborators> assigneesList, Dialog dialogAssignees, AssigneesListAdapter assigneesAdapter, CustomAssigneesSelectionDialogBinding assigneesBinding) {
TinyDB tinyDB = new TinyDB(ctx);
TinyDB tinyDB = TinyDB.getInstance(ctx);
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getCollaborators(instanceToken, repoOwner, repoName);
.getApiInterface(ctx)
.getCollaborators(Authorization.get(ctx), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@ -89,8 +87,6 @@ public class AssigneesActions {
if(assigneesList_.size() > 0) {
dialogAssignees.show();
assigneesList.add(new Collaborators(tinyDB.getString("userFullname"), tinyDB.getString("loginUid"), tinyDB.getString("userAvatar")));
assigneesList.addAll(assigneesList_);
}

View File

@ -3,6 +3,8 @@ package org.mian.gitnex.actions;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.Collaborators;
import org.gitnex.tea4j.models.Permission;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.AddCollaboratorToRepositoryActivity;
import org.mian.gitnex.clients.RetrofitClient;
@ -10,8 +12,6 @@ import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Permission;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
@ -25,21 +25,16 @@ public class CollaboratorActions {
public static void deleteCollaborator(final Context context, final String searchKeyword, String userName) {
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");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<Collaborators> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.deleteCollaborator(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, userName);
Call<Collaborators> call = RetrofitClient
.getApiInterface(context)
.deleteCollaborator(Authorization.get(context), repoOwner, repoName, userName);
call.enqueue(new Callback<Collaborators>() {
@ -54,7 +49,7 @@ public class CollaboratorActions {
//Log.i("addCollaboratorSearch", addCollaboratorSearch.getText().toString());
//tinyDb.putBoolean("updateDataSet", true);
//AddCollaboratorToRepositoryActivity usersSearchData = new AddCollaboratorToRepositoryActivity();
//usersSearchData.loadUserSearchList(instanceUrl, instanceToken, searchKeyword, context);
//usersSearchData.loadUserSearchList(instanceToken, searchKeyword, context);
}
}
@ -94,22 +89,18 @@ public class CollaboratorActions {
public static void addCollaborator(final Context context, String permission, String userName) {
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");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Permission permissionString = new Permission(permission);
Call<Permission> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.addCollaborator(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, userName, permissionString);
Call<Permission> call = RetrofitClient
.getApiInterface(context)
.addCollaborator(Authorization.get(context), repoOwner, repoName, userName, permissionString);
call.enqueue(new Callback<Permission>() {
@ -122,7 +113,7 @@ public class CollaboratorActions {
Toasty.success(context, context.getString(R.string.addCollaboratorToastText));
((AddCollaboratorToRepositoryActivity)context).finish();
//AddCollaboratorToRepositoryActivity usersSearchData = new AddCollaboratorToRepositoryActivity();
//usersSearchData.loadUserSearchList(instanceUrl, instanceToken, searchKeyword, context);
//usersSearchData.loadUserSearchList(instanceToken, searchKeyword, context);
}
}
@ -164,11 +155,7 @@ public class CollaboratorActions {
public static ActionResult<List<Collaborators>> getCollaborators(Context context) {
ActionResult<List<Collaborators>> actionResult = new ActionResult<>();
TinyDB tinyDb = new TinyDB(context);
String instanceUrl = tinyDb.getString("instanceUrl");
String loginUid = tinyDb.getString("loginUid");
String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
@ -176,9 +163,8 @@ public class CollaboratorActions {
String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(context)
.getCollaborators(Authorization.get(context), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {

View File

@ -3,18 +3,18 @@ package org.mian.gitnex.actions;
import android.content.Context;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.gitnex.tea4j.models.IssueComments;
import org.gitnex.tea4j.models.Issues;
import org.gitnex.tea4j.models.UpdateIssueState;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.IssueComments;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.UpdateIssueState;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -22,85 +22,72 @@ import retrofit2.Callback;
public class IssueActions {
public static void editIssueComment(final Context ctx, final int commentId, final String commentBody, long draftIdOnCreate) {
public static ActionResult<Response<?>> edit(Context context, String comment, int commentId) {
ActionResult<Response<?>> actionResult = new ActionResult<>();
TinyDB tinyDb = TinyDB.getInstance(context);
final TinyDB tinyDb = new TinyDB(ctx);
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];
IssueComments commentBodyJson = new IssueComments(commentBody);
Call<IssueComments> call;
String repoOwner = parts[0];
String repoName = parts[1];
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().patchIssueComment(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, commentId, commentBodyJson);
Call<IssueComments> call = RetrofitClient
.getApiInterface(context)
.patchIssueComment(Authorization.get(context), repoOwner, repoName, commentId, new IssueComments(comment));
call.enqueue(new Callback<IssueComments>() {
@Override
public void onResponse(@NonNull Call<IssueComments> call, @NonNull retrofit2.Response<IssueComments> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
switch(response.code()) {
tinyDb.putBoolean("commentEdited", true);
Toasty.info(ctx, ctx.getString(R.string.editCommentUpdatedText));
case 200:
actionResult.finish(ActionResult.Status.SUCCESS);
break;
DraftsApi draftsApi = new DraftsApi(ctx);
draftsApi.deleteSingleDraft((int) draftIdOnCreate);
case 401:
actionResult.finish(ActionResult.Status.FAILED, response);
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));
break;
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle), ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
default:
actionResult.finish(ActionResult.Status.FAILED, response);
break;
}
else if(response.code() == 403) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<IssueComments> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
actionResult.finish(ActionResult.Status.FAILED);
}
});
return actionResult;
}
public static void closeReopenIssue(final Context ctx, final int issueIndex, final String issueState) {
final TinyDB tinyDb = new TinyDB(ctx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final TinyDB tinyDb = TinyDB.getInstance(ctx);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
UpdateIssueState issueStatJson = new UpdateIssueState(issueState);
Call<JsonElement> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().closeReopenIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueStatJson);
call = RetrofitClient
.getApiInterface(ctx)
.closeReopenIssue(Authorization.get(ctx), repoOwner, repoName, issueIndex, issueStatJson);
call.enqueue(new Callback<JsonElement>() {
@ -162,20 +149,23 @@ public class IssueActions {
public static void subscribe(final Context ctx) {
final TinyDB tinyDB = new TinyDB(ctx);
final TinyDB tinyDB = TinyDB.getInstance(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String[] repoFullName = tinyDB.getString("repoFullName").split("/");
if(repoFullName.length != 2) {
return;
}
final String userLogin = tinyDB.getString("userLogin");
final String token = "token " + tinyDB.getString(tinyDB.getString("loginUid") + "-token");
final int issueNr = Integer.parseInt(tinyDB.getString("issueNumber"));
Call<Void> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().addIssueSubscriber(token, repoFullName[0], repoFullName[1], issueNr, userLogin);
call = RetrofitClient
.getApiInterface(ctx)
.addIssueSubscriber(token, repoFullName[0], repoFullName[1], issueNr, userLogin);
call.enqueue(new Callback<Void>() {
@ -222,9 +212,8 @@ public class IssueActions {
public static void unsubscribe(final Context ctx) {
final TinyDB tinyDB = new TinyDB(ctx);
final TinyDB tinyDB = TinyDB.getInstance(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String[] repoFullName = tinyDB.getString("repoFullName").split("/");
if(repoFullName.length != 2) {
return;
@ -235,7 +224,7 @@ public class IssueActions {
Call<Void> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().delIssueSubscriber(token, repoFullName[0], repoFullName[1], issueNr, userLogin);
call = RetrofitClient.getApiInterface(ctx).delIssueSubscriber(token, repoFullName[0], repoFullName[1], issueNr, userLogin);
call.enqueue(new Callback<Void>() {
@ -265,7 +254,7 @@ public class IssueActions {
}
else {
Toasty.error(ctx, ctx.getString(R.string.unsubscriptionError));
Toasty.error(ctx, ctx.getString(R.string.unSubscriptionError));
}
@ -282,11 +271,8 @@ public class IssueActions {
public static ActionResult<ActionResult.None> reply(Context context, String comment, int issueIndex) {
ActionResult<ActionResult.None> actionResult = new ActionResult<>();
TinyDB tinyDb = new TinyDB(context);
String instanceUrl = tinyDb.getString("instanceUrl");
String loginUid = tinyDb.getString("loginUid");
String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
@ -296,9 +282,8 @@ public class IssueActions {
Issues issueComment = new Issues(comment);
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.replyCommentToIssue(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueComment);
.getApiInterface(context)
.replyCommentToIssue(Authorization.get(context), repoOwner, repoName, issueIndex, issueComment);
call.enqueue(new Callback<Issues>() {

View File

@ -5,13 +5,13 @@ import android.content.Context;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.Labels;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.LabelsListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Labels;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
@ -22,12 +22,11 @@ import retrofit2.Callback;
public class LabelsActions {
public static void getCurrentIssueLabels(Context ctx, String instanceUrl, String loginUid, String instanceToken, String repoOwner, String repoName, int issueIndex, List<Integer> currentLabelsIds) {
public static void getCurrentIssueLabels(Context ctx, String repoOwner, String repoName, int issueIndex, List<Integer> currentLabelsIds) {
Call<List<Labels>> callSingleIssueLabels = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getIssueLabels(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex);
.getApiInterface(ctx)
.getIssueLabels(Authorization.get(ctx), repoOwner, repoName, issueIndex);
callSingleIssueLabels.enqueue(new Callback<List<Labels>>() {
@ -60,12 +59,11 @@ public class LabelsActions {
});
}
public static void getRepositoryLabels(Context ctx, String instanceUrl, String instanceToken, String repoOwner, String repoName, List<Labels> labelsList, Dialog dialogLabels, LabelsListAdapter labelsAdapter, CustomLabelsSelectionDialogBinding labelsBinding) {
public static void getRepositoryLabels(Context ctx, String repoOwner, String repoName, List<Labels> labelsList, Dialog dialogLabels, LabelsListAdapter labelsAdapter, CustomLabelsSelectionDialogBinding labelsBinding) {
Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getlabels(instanceToken, repoOwner, repoName);
.getApiInterface(ctx)
.getLabels(Authorization.get(ctx), repoOwner, repoName);
call.enqueue(new Callback<List<Labels>>() {
@ -73,28 +71,45 @@ public class LabelsActions {
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> response) {
labelsList.clear();
List<Labels> labelsList_ = response.body();
labelsBinding.progressBar.setVisibility(View.GONE);
labelsBinding.dialogFrame.setVisibility(View.VISIBLE);
if (response.code() == 200) {
assert labelsList_ != null;
if(response.body() != null) {
if(labelsList_.size() > 0) {
dialogLabels.show();
labelsList.addAll(labelsList_);
}
else {
dialogLabels.dismiss();
Toasty.warning(ctx, ctx.getResources().getString(R.string.noLabelsFound));
labelsList.addAll(response.body());
}
labelsBinding.labelsRecyclerView.setAdapter(labelsAdapter);
// Load organization labels
Call<List<Labels>> callOrgLabels = RetrofitClient
.getApiInterface(ctx)
.getOrganizationLabels(Authorization.get(ctx), repoOwner);
callOrgLabels.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> responseOrg) {
labelsBinding.progressBar.setVisibility(View.GONE);
labelsBinding.dialogFrame.setVisibility(View.VISIBLE);
if(responseOrg.body() != null) {
labelsList.addAll(responseOrg.body());
}
if(labelsList.isEmpty()) {
dialogLabels.dismiss();
Toasty.warning(ctx, ctx.getResources().getString(R.string.noLabelsFound));
}
labelsBinding.labelsRecyclerView.setAdapter(labelsAdapter);
}
@Override public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {}
});
}
else {

View File

@ -4,12 +4,12 @@ import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.gitnex.tea4j.models.Milestones;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Milestones;
import retrofit2.Call;
import retrofit2.Callback;
@ -23,9 +23,8 @@ public class MilestoneActions {
public static void closeMilestone(final Context ctx, int milestoneId_) {
final TinyDB tinyDB = new TinyDB(ctx);
final TinyDB tinyDB = TinyDB.getInstance(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -37,8 +36,7 @@ public class MilestoneActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.closeReopenMilestone(token, repoOwner, repoName, milestoneId_, milestoneStateJson);
call.enqueue(new Callback<JsonElement>() {
@ -81,9 +79,8 @@ public class MilestoneActions {
public static void openMilestone(final Context ctx, int milestoneId_) {
final TinyDB tinyDB = new TinyDB(ctx);
final TinyDB tinyDB = TinyDB.getInstance(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -95,8 +92,7 @@ public class MilestoneActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.closeReopenMilestone(token, repoOwner, repoName, milestoneId_, milestoneStateJson);
call.enqueue(new Callback<JsonElement>() {

View File

@ -1,13 +1,12 @@
package org.mian.gitnex.actions;
import android.content.Context;
import org.gitnex.tea4j.models.NotificationThread;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.NotificationThread;
import java.io.IOException;
import java.util.Date;
import okhttp3.ResponseBody;
import retrofit2.Call;
/**
@ -20,24 +19,22 @@ public class NotificationsActions {
private TinyDB tinyDB;
private Context context;
private String instanceUrl;
private String instanceToken;
public NotificationsActions(Context context) {
this.context = context;
this.tinyDB = new TinyDB(context);
this.tinyDB = TinyDB.getInstance(context);
String loginUid = tinyDB.getString("loginUid");
instanceUrl = tinyDB.getString("instanceUrl");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
}
public void setNotificationStatus(NotificationThread notificationThread, NotificationStatus notificationStatus) throws IOException {
Call<ResponseBody> call = RetrofitClient.getInstance(instanceUrl, context).getApiInterface()
Call<Void> call = RetrofitClient.getApiInterface(context)
.markNotificationThreadAsRead(instanceToken, notificationThread.getId(), notificationStatus.name());
if(!call.execute().isSuccessful()) {
@ -48,7 +45,7 @@ public class NotificationsActions {
public boolean setAllNotificationsRead(Date date) throws IOException {
Call<ResponseBody> call = RetrofitClient.getInstance(instanceUrl, context).getApiInterface()
Call<Void> call = RetrofitClient.getApiInterface(context)
.markNotificationThreadsAsRead(instanceToken, AppUtil.getTimestampFromDate(context, date), true,
new String[]{"unread", "pinned"}, "read");

View File

@ -0,0 +1,102 @@
package org.mian.gitnex.actions;
import android.content.Context;
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 retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author qwerty287
*/
public class PullRequestActions {
public static void deleteHeadBranch(Context context, String repoOwner, String repoName, String headBranch, boolean showToasts) {
Call<JsonElement> call = RetrofitClient
.getApiInterface(context)
.deleteBranch(Authorization.get(context), repoOwner, repoName, headBranch);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 204) {
if(showToasts) Toasty.success(context, context.getString(R.string.deleteBranchSuccess));
}
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) {
if(showToasts) Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
if(showToasts) Toasty.warning(context, context.getString(R.string.deleteBranchErrorNotFound));
}
else {
if(showToasts) Toasty.error(context, context.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
if(showToasts) Toasty.error(context, context.getString(R.string.deleteBranchError));
}
});
}
public static void updatePr(Context context, String repoOwner, String repoName, String index, Boolean rebase) {
String strategy;
if(rebase == null) {
strategy = null;
}
else if(!rebase) {
strategy = "merge";
}
else {
strategy = "rebase";
}
RetrofitClient.getApiInterface(context).updatePullRequest(Authorization.get(context), repoOwner, repoName, Integer.parseInt(index), strategy)
.enqueue(new Callback<Void>() {
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) {
if(response.isSuccessful()) {
Toasty.success(context, context.getString(R.string.updatePrSuccess));
}
else {
if(response.code() == 403) {
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 409) {
Toasty.error(context, context.getString(R.string.updatePrConflict));
}
else {
Toasty.error(context, context.getString(R.string.genericError));
}
}
}
@Override
public void onFailure(@NonNull Call call, @NonNull Throwable t) {
Toasty.error(context, context.getString(R.string.genericError));
}
});
}
}

View File

@ -21,10 +21,8 @@ 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");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -33,9 +31,8 @@ public class RepositoryActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.starRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(context)
.starRepository(Authorization.get(context), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {
@ -86,10 +83,8 @@ public class RepositoryActions {
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");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -98,9 +93,8 @@ public class RepositoryActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.unStarRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(context)
.unStarRepository(Authorization.get(context), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {
@ -151,10 +145,8 @@ public class RepositoryActions {
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");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -163,9 +155,8 @@ public class RepositoryActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.watchRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(context)
.watchRepository(Authorization.get(context), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {
@ -216,10 +207,8 @@ public class RepositoryActions {
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");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -228,9 +217,8 @@ public class RepositoryActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.unWatchRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(context)
.unWatchRepository(Authorization.get(context), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {

View File

@ -21,17 +21,13 @@ public class TeamActions {
public static void removeTeamMember(final Context context, String userName, int teamId) {
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");
final TinyDB tinyDb = TinyDB.getInstance(context);
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.removeTeamMember(Authorization.returnAuthentication(context, loginUid, instanceToken), teamId, userName);
.getApiInterface(context)
.removeTeamMember(Authorization.get(context), teamId, userName);
call.enqueue(new Callback<JsonElement>() {
@ -87,17 +83,11 @@ public class TeamActions {
public static void addTeamMember(final Context context, String userName, int teamId) {
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");
final TinyDB tinyDb = TinyDB.getInstance(context);
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.addTeamMember(Authorization.returnAuthentication(context, loginUid, instanceToken), teamId, userName);
Call<JsonElement> call = RetrofitClient
.getApiInterface(context)
.addTeamMember(Authorization.get(context), teamId, userName);
call.enqueue(new Callback<JsonElement>() {

View File

@ -13,13 +13,12 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.gitnex.tea4j.models.UserInfo;
import org.gitnex.tea4j.models.UserSearch;
import org.mian.gitnex.adapters.UserSearchAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityAddCollaboratorToRepositoryBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.models.UserSearch;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
@ -32,39 +31,27 @@ import retrofit2.Response;
public class AddCollaboratorToRepositoryActivity extends BaseActivity {
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private TextView addCollaboratorSearch;
private TextView noData;
private ProgressBar mProgressBar;
private RecyclerView mRecyclerView;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_add_collaborator_to_repository;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
ActivityAddCollaboratorToRepositoryBinding activityAddCollaboratorToRepositoryBinding = ActivityAddCollaboratorToRepositoryBinding.inflate(getLayoutInflater());
setContentView(activityAddCollaboratorToRepositoryBinding.getRoot());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
addCollaboratorSearch = findViewById(R.id.addCollaboratorSearch);
mRecyclerView = findViewById(R.id.recyclerViewUserSearch);
mProgressBar = findViewById(R.id.progressBar);
noData = findViewById(R.id.noData);
ImageView closeActivity = activityAddCollaboratorToRepositoryBinding.close;
addCollaboratorSearch = activityAddCollaboratorToRepositoryBinding.addCollaboratorSearch;
mRecyclerView = activityAddCollaboratorToRepositoryBinding.recyclerViewUserSearch;
mProgressBar = activityAddCollaboratorToRepositoryBinding.progressBar;
noData = activityAddCollaboratorToRepositoryBinding.noData;
addCollaboratorSearch.requestFocus();
assert imm != null;
@ -80,7 +67,7 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
if(!addCollaboratorSearch.getText().toString().equals("")) {
mProgressBar.setVisibility(View.VISIBLE);
loadUserSearchList(instanceUrl, instanceToken, addCollaboratorSearch.getText().toString(), loginUid);
loadUserSearchList(addCollaboratorSearch.getText().toString());
}
}
@ -90,12 +77,11 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
}
public void loadUserSearchList(String instanceUrl, String token, String searchKeyword, String loginUid) {
public void loadUserSearchList(String searchKeyword) {
Call<UserSearch> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getUserBySearch(Authorization.returnAuthentication(ctx, loginUid, token), searchKeyword, 10);
.getApiInterface(appCtx)
.getUserBySearch(Authorization.get(ctx), searchKeyword, 10, 1);
call.enqueue(new Callback<UserSearch>() {
@ -140,14 +126,13 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
mRecyclerView.setAdapter(adapter);
noData.setVisibility(View.GONE);
mProgressBar.setVisibility(View.GONE);
}
else {
noData.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
mProgressBar.setVisibility(View.GONE);
}
private void initCloseListener() {

View File

@ -1,6 +1,5 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
@ -9,18 +8,18 @@ import android.view.View;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import org.gitnex.tea4j.models.GiteaVersion;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.databinding.ActivityAddNewAccountBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.PathsHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.models.UserInfo;
import java.net.URI;
import io.mikael.urlbuilder.UrlBuilder;
import retrofit2.Call;
@ -32,43 +31,30 @@ import retrofit2.Callback;
public class AddNewAccountActivity extends BaseActivity {
final Context ctx = this;
private Context appCtx;
private TinyDB tinyDB;
private View.OnClickListener onClickListener;
private ActivityAddNewAccountBinding viewBinding;
private enum Protocol {HTTPS, HTTP}
private String spinnerSelectedValue;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_add_new_account;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDB = new TinyDB(appCtx);
viewBinding = ActivityAddNewAccountBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
setContentView(viewBinding.getRoot());
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
initCloseListener();
viewBinding.close.setOnClickListener(onClickListener);
viewBinding.instanceUrl.setText(getIntent().getStringExtra("instanceUrl"));
ArrayAdapter<Protocol> adapterProtocols = new ArrayAdapter<>(ctx, R.layout.list_spinner_items, Protocol.values());
viewBinding.protocolSpinner.setAdapter(adapterProtocols);
viewBinding.protocolSpinner.setOnItemClickListener((parent, view1, position, id) -> spinnerSelectedValue = String.valueOf(parent.getItemAtPosition(position)));
viewBinding.addNewAccount.setOnClickListener(login -> {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
@ -76,7 +62,6 @@ public class AddNewAccountActivity extends BaseActivity {
if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
}
else {
@ -131,9 +116,7 @@ public class AddNewAccountActivity extends BaseActivity {
private void versionCheck(final String instanceUrl, final String loginToken) {
Call<GiteaVersion> callVersion;
callVersion = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getGiteaVersionWithToken("token " + loginToken);
callVersion = RetrofitClient.getApiInterface(ctx, instanceUrl).getGiteaVersionWithToken("token " + loginToken);
callVersion.enqueue(new Callback<GiteaVersion>() {
@Override
@ -144,7 +127,9 @@ public class AddNewAccountActivity extends BaseActivity {
GiteaVersion version = responseVersion.body();
assert version != null;
if(!Version.valid(version.getVersion())) {
Toasty.error(ctx, getResources().getString(R.string.versionUnknown));
return;
}
@ -158,7 +143,7 @@ public class AddNewAccountActivity extends BaseActivity {
.setMessage(getResources().getString(R.string.versionUnsupportedOld, version.getVersion())).setIcon(R.drawable.ic_warning)
.setCancelable(true);
alertDialogBuilder.setNegativeButton(getString(R.string.cancelButton), (dialog, which) -> {
alertDialogBuilder.setNeutralButton(getString(R.string.cancelButton), (dialog, which) -> {
dialog.dismiss();
});
@ -170,7 +155,6 @@ public class AddNewAccountActivity extends BaseActivity {
});
alertDialogBuilder.create().show();
}
else if(giteaVersion.lessOrEqual(getString(R.string.versionHigh))) {
@ -180,7 +164,6 @@ public class AddNewAccountActivity extends BaseActivity {
Toasty.warning(ctx, getResources().getString(R.string.versionUnsupportedNew));
login(instanceUrl, loginToken);
}
}
@ -193,7 +176,6 @@ public class AddNewAccountActivity extends BaseActivity {
private void login(String instanceUrl, String loginToken) {
setupNewAccountWithToken(instanceUrl, loginToken);
}
@Override
@ -207,7 +189,7 @@ public class AddNewAccountActivity extends BaseActivity {
private void setupNewAccountWithToken(String instanceUrl, final String loginToken) {
Call<UserInfo> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserInfo("token " + loginToken);
Call<UserInfo> call = RetrofitClient.getApiInterface(ctx, instanceUrl).getUserInfo("token " + loginToken);
call.enqueue(new Callback<UserInfo>() {
@ -223,14 +205,15 @@ public class AddNewAccountActivity extends BaseActivity {
assert userDetails != null;
// insert new account to db if does not exist
String accountName = userDetails.getUsername() + "@" + instanceUrl;
UserAccountsApi userAccountsApi = new UserAccountsApi(ctx);
int checkAccount = userAccountsApi.getCount(accountName);
UserAccountsApi userAccountsApi = BaseApi.getInstance(ctx, UserAccountsApi.class);
boolean userAccountExists = userAccountsApi.userAccountExists(accountName);
if(checkAccount == 0) {
if(!userAccountExists) {
userAccountsApi.insertNewAccount(accountName, instanceUrl, userDetails.getUsername(), loginToken, "");
userAccountsApi.createNewAccount(accountName, instanceUrl, userDetails.getUsername(), loginToken, "");
Toasty.success(ctx, getResources().getString(R.string.accountAddedMessage));
finish();
}
else {

View File

@ -14,13 +14,12 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.gitnex.tea4j.models.UserInfo;
import org.gitnex.tea4j.models.UserSearch;
import org.mian.gitnex.adapters.UserSearchForTeamMemberAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityAddNewTeamMemberBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.models.UserSearch;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@ -35,8 +34,6 @@ import retrofit2.Response;
public class AddNewTeamMemberActivity extends BaseActivity {
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private TextView addNewTeamMember;
private TextView noData;
private ProgressBar mProgressBar;
@ -47,31 +44,21 @@ public class AddNewTeamMemberActivity extends BaseActivity {
private String teamId;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_add_new_team_member;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
ActivityAddNewTeamMemberBinding activityAddNewTeamMemberBinding = ActivityAddNewTeamMemberBinding.inflate(getLayoutInflater());
setContentView(activityAddNewTeamMemberBinding.getRoot());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
addNewTeamMember = findViewById(R.id.addNewTeamMember);
mRecyclerView = findViewById(R.id.recyclerViewUserSearch);
mProgressBar = findViewById(R.id.progress_bar);
noData = findViewById(R.id.noData);
ImageView closeActivity = activityAddNewTeamMemberBinding.close;
addNewTeamMember = activityAddNewTeamMemberBinding.addNewTeamMember;
mRecyclerView = activityAddNewTeamMemberBinding.recyclerViewUserSearch;
mProgressBar = activityAddNewTeamMemberBinding.progressBar;
noData = activityAddNewTeamMemberBinding.noData;
addNewTeamMember.requestFocus();
assert imm != null;
@ -81,9 +68,11 @@ public class AddNewTeamMemberActivity extends BaseActivity {
closeActivity.setOnClickListener(onClickListener);
if(getIntent().getStringExtra("teamId") != null && !Objects.requireNonNull(getIntent().getStringExtra("teamId")).equals("")) {
teamId = getIntent().getStringExtra("teamId");
}
else {
teamId = "0";
}
@ -103,10 +92,8 @@ public class AddNewTeamMemberActivity extends BaseActivity {
if(!addNewTeamMember.getText().toString().equals("") && addNewTeamMember.getText().toString().length() > 1) {
adapter = new UserSearchForTeamMemberAdapter(dataList, ctx, Integer.parseInt(teamId));
loadUserSearchList(instanceUrl, instanceToken, addNewTeamMember.getText().toString(), loginUid, teamId);
loadUserSearchList(addNewTeamMember.getText().toString(), teamId);
}
}
@Override
@ -121,9 +108,9 @@ public class AddNewTeamMemberActivity extends BaseActivity {
}
public void loadUserSearchList(String instanceUrl, String token, String searchKeyword, String loginUid, String teamId) {
public void loadUserSearchList(String searchKeyword, String teamId) {
Call<UserSearch> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserBySearch(Authorization.returnAuthentication(ctx, loginUid, token), searchKeyword, 10);
Call<UserSearch> call = RetrofitClient.getApiInterface(ctx).getUserBySearch(Authorization.get(ctx), searchKeyword, 10, 1);
mProgressBar.setVisibility(View.VISIBLE);
@ -141,16 +128,13 @@ public class AddNewTeamMemberActivity extends BaseActivity {
dataList.addAll(response.body().getData());
mRecyclerView.setAdapter(adapter);
noData.setVisibility(View.GONE);
mProgressBar.setVisibility(View.GONE);
}
else {
noData.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
mProgressBar.setVisibility(View.GONE);
}
}

View File

@ -0,0 +1,89 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.mian.gitnex.adapters.AdminCronTasksAdapter;
import org.mian.gitnex.databinding.ActivityAdminCronTasksBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.viewmodels.AdminCronTasksViewModel;
/**
* Author M M Arif
*/
public class AdminCronTasksActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private AdminCronTasksAdapter adapter;
private ActivityAdminCronTasksBinding activityAdminCronTasksBinding;
public static final int PAGE = 1;
public static final int LIMIT = 50;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityAdminCronTasksBinding = ActivityAdminCronTasksBinding.inflate(getLayoutInflater());
setContentView(activityAdminCronTasksBinding.getRoot());
initCloseListener();
activityAdminCronTasksBinding.close.setOnClickListener(onClickListener);
Toolbar toolbar = activityAdminCronTasksBinding.toolbar;
setSupportActionBar(toolbar);
activityAdminCronTasksBinding.recyclerView.setHasFixedSize(true);
activityAdminCronTasksBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(activityAdminCronTasksBinding.recyclerView.getContext(),
DividerItemDecoration.VERTICAL);
activityAdminCronTasksBinding.recyclerView.addItemDecoration(dividerItemDecoration);
activityAdminCronTasksBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
activityAdminCronTasksBinding.pullToRefresh.setRefreshing(false);
AdminCronTasksViewModel.loadCronTasksList(ctx, Authorization.get(ctx), PAGE, LIMIT);
}, 500));
fetchDataAsync(ctx, Authorization.get(ctx));
}
private void fetchDataAsync(Context ctx, String instanceToken) {
AdminCronTasksViewModel cronTasksViewModel = new ViewModelProvider(this).get(AdminCronTasksViewModel.class);
cronTasksViewModel.getCronTasksList(ctx, instanceToken, PAGE, LIMIT).observe(this, cronTasksListMain -> {
adapter = new AdminCronTasksAdapter(ctx, cronTasksListMain);
if(adapter.getItemCount() > 0) {
activityAdminCronTasksBinding.recyclerView.setVisibility(View.VISIBLE);
activityAdminCronTasksBinding.recyclerView.setAdapter(adapter);
activityAdminCronTasksBinding.noData.setVisibility(View.GONE);
}
else {
activityAdminCronTasksBinding.recyclerView.setVisibility(View.GONE);
activityAdminCronTasksBinding.noData.setVisibility(View.VISIBLE);
}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -21,10 +21,10 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.AdminGetUsersAdapter;
import org.mian.gitnex.databinding.ActivityAdminGetUsersBinding;
import org.mian.gitnex.fragments.BottomSheetAdminUsersFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.viewmodels.AdminGetUsersViewModel;
/**
@ -34,36 +34,26 @@ import org.mian.gitnex.viewmodels.AdminGetUsersViewModel;
public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAdminUsersFragment.BottomSheetListener {
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private AdminGetUsersAdapter adapter;
private RecyclerView mRecyclerView;
private TextView noDataUsers;
private Boolean searchFilter = false;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_admin_get_users;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ActivityAdminGetUsersBinding activityAdminGetUsersBinding = ActivityAdminGetUsersBinding.inflate(getLayoutInflater());
setContentView(activityAdminGetUsersBinding.getRoot());
ImageView closeActivity = findViewById(R.id.close);
noDataUsers = findViewById(R.id.noDataUsers);
mRecyclerView = findViewById(R.id.recyclerView);
ImageView closeActivity = activityAdminGetUsersBinding.close;
noDataUsers = activityAdminGetUsersBinding.noDataUsers;
mRecyclerView = activityAdminGetUsersBinding.recyclerView;
final SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh);
final SwipeRefreshLayout swipeRefresh = activityAdminGetUsersBinding.pullToRefresh;
Toolbar toolbar = findViewById(R.id.toolbar);
Toolbar toolbar = activityAdminGetUsersBinding.toolbar;
setSupportActionBar(toolbar);
initCloseListener();
@ -79,30 +69,30 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
AdminGetUsersViewModel.loadUsersList(ctx, instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken));
AdminGetUsersViewModel.loadUsersList(ctx, Authorization.get(ctx));
}, 500));
fetchDataAsync(ctx, instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken));
fetchDataAsync(ctx, Authorization.get(ctx));
}
private void fetchDataAsync(Context ctx, String instanceUrl, String instanceToken) {
private void fetchDataAsync(Context ctx, String instanceToken) {
AdminGetUsersViewModel usersModel = new ViewModelProvider(this).get(AdminGetUsersViewModel.class);
usersModel.getUsersList(ctx, instanceUrl, instanceToken).observe(this, usersListMain -> {
usersModel.getUsersList(ctx, instanceToken).observe(this, usersListMain -> {
adapter = new AdminGetUsersAdapter(ctx, usersListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setVisibility(View.VISIBLE);
mRecyclerView.setAdapter(adapter);
noDataUsers.setVisibility(View.GONE);
searchFilter = true;
}
else {
//adapter.notifyDataSetChanged();
//mRecyclerView.setAdapter(adapter);
mRecyclerView.setVisibility(View.GONE);
noDataUsers.setVisibility(View.VISIBLE);
}
@ -140,6 +130,7 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
@ -157,18 +148,21 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
int id = item.getItemId();
switch (id) {
case android.R.id.home:
finish();
return true;
case R.id.genericMenu:
BottomSheetAdminUsersFragment bottomSheet = new BottomSheetAdminUsersFragment();
bottomSheet.show(getSupportFragmentManager(), "usersBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
if(id == android.R.id.home) {
finish();
return true;
}
else if(id == R.id.genericMenu) {
BottomSheetAdminUsersFragment bottomSheet = new BottomSheetAdminUsersFragment();
bottomSheet.show(getSupportFragmentManager(), "usersBottomSheet");
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
@Override

View File

@ -2,155 +2,135 @@ package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import org.acra.ACRA;
import org.acra.BuildConfig;
import org.acra.annotation.AcraCore;
import org.acra.annotation.AcraNotification;
import org.acra.config.CoreConfigurationBuilder;
import org.acra.config.LimiterConfigurationBuilder;
import org.acra.config.MailSenderConfigurationBuilder;
import org.acra.data.StringFormat;
import androidx.biometric.BiometricPrompt;
import androidx.core.content.ContextCompat;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.FontsOverride;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.notifications.NotificationsMaster;
import static org.acra.ReportField.ANDROID_VERSION;
import static org.acra.ReportField.PHONE_MODEL;
import static org.acra.ReportField.STACK_TRACE;
import org.mian.gitnex.notifications.Notifications;
import java.util.Locale;
import java.util.concurrent.Executor;
/**
* Author M M Arif
*/
@AcraNotification(resIcon = R.drawable.gitnex_transparent,
resTitle = R.string.crashTitle,
resChannelName = R.string.setCrashReports,
resText = R.string.crashMessage)
@AcraCore(reportContent = { ANDROID_VERSION, PHONE_MODEL, STACK_TRACE })
public abstract class BaseActivity extends AppCompatActivity {
private Context appCtx;
protected TinyDB tinyDB;
protected Context ctx = this;
protected Context appCtx;
@Override
public void onCreate(Bundle savedInstanceState) {
appCtx = getApplicationContext();
final TinyDB tinyDb = new TinyDB(appCtx);
super.onCreate(savedInstanceState);
switch(tinyDb.getInt("themeId")) {
this.appCtx = getApplicationContext();
this.tinyDB = TinyDB.getInstance(appCtx);
switch(tinyDB.getInt("themeId")) {
case 1:
tinyDB.putString("currentTheme", "light");
setTheme(R.style.AppThemeLight);
break;
case 2:
if(TimeHelper.timeBetweenHours(18, 6)) { // 6pm to 6am
if(TimeHelper.timeBetweenHours(tinyDB.getInt("darkThemeTimeHour"), tinyDB.getInt("lightThemeTimeHour"), tinyDB.getInt("darkThemeTimeMinute"), tinyDB.getInt("lightThemeTimeMinute"))) {
tinyDB.putString("currentTheme", "dark");
setTheme(R.style.AppTheme);
}
else {
tinyDB.putString("currentTheme", "light");
setTheme(R.style.AppThemeLight);
}
break;
case 3:
tinyDB.putString("currentTheme", "light");
setTheme(R.style.AppThemeRetro);
break;
case 4:
if(TimeHelper.timeBetweenHours(18, 6)) { // 6pm to 6am
if(TimeHelper.timeBetweenHours(tinyDB.getInt("darkThemeTimeHour"), tinyDB.getInt("lightThemeTimeHour"), tinyDB.getInt("darkThemeTimeMinute"), tinyDB.getInt("lightThemeTimeMinute"))) {
tinyDB.putString("currentTheme", "dark");
setTheme(R.style.AppTheme);
}
else {
tinyDB.putString("currentTheme", "light");
setTheme(R.style.AppThemeRetro);
}
break;
case 5:
tinyDB.putString("currentTheme", "dark");
setTheme(R.style.AppThemePitchBlack);
break;
default:
tinyDB.putString("currentTheme", "dark");
setTheme(R.style.AppTheme);
break;
}
String appLocale = tinyDb.getString("locale");
AppUtil.setAppLocale(getResources(), appLocale);
super.onCreate(savedInstanceState);
setContentView(getLayoutResourceId());
switch(tinyDb.getInt("customFontId", -1)) {
case 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");
break;
case 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");
break;
default:
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");
break;
String locale = tinyDB.getString("locale");
if (locale.isEmpty()) {
AppUtil.setAppLocale(getResources(), Locale.getDefault().getLanguage());
}
else {
AppUtil.setAppLocale(getResources(), locale);
}
if(tinyDb.getInt("pollingDelayMinutes") == 0) {
tinyDb.putInt("pollingDelayMinutes", 15);
}
Notifications.startWorker(appCtx);
}
NotificationsMaster.hireWorker(appCtx);
public void onResume() {
super.onResume();
// enabling counter badges by default
if(tinyDb.getString("enableCounterBadgesInit").isEmpty()) {
tinyDb.putBoolean("enableCounterBadges", true);
tinyDb.putString("enableCounterBadgesInit", "yes");
}
if(tinyDB.getBoolean("biometricStatus") && !tinyDB.getBoolean("biometricLifeCycle")) {
// enable crash reports by default
if(tinyDb.getString("crashReportingEnabledInit").isEmpty()) {
tinyDb.putBoolean("crashReportingEnabled", true);
tinyDb.putString("crashReportingEnabledInit", "yes");
}
Executor executor = ContextCompat.getMainExecutor(this);
// default cache setter
if(tinyDb.getString("cacheSizeStr").isEmpty()) {
tinyDb.putString("cacheSizeStr", getResources().getString(R.string.cacheSizeDataSelectionSelectedText));
}
if(tinyDb.getString("cacheSizeImagesStr").isEmpty()) {
tinyDb.putString("cacheSizeImagesStr", getResources().getString(R.string.cacheSizeImagesSelectionSelectedText));
}
BiometricPrompt biometricPrompt = new BiometricPrompt(this, executor, new BiometricPrompt.AuthenticationCallback() {
// enable comment drafts by default
if(tinyDb.getString("draftsCommentsDeletionEnabledInit").isEmpty()) {
tinyDb.putBoolean("draftsCommentsDeletionEnabled", true);
tinyDb.putString("draftsCommentsDeletionEnabledInit", "yes");
}
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
if (tinyDb.getBoolean("crashReportingEnabled")) {
super.onAuthenticationError(errorCode, errString);
CoreConfigurationBuilder ACRABuilder = new CoreConfigurationBuilder(this);
ACRABuilder.setBuildConfigClass(BuildConfig.class).setReportFormat(StringFormat.KEY_VALUE_LIST);
ACRABuilder.getPluginConfigurationBuilder(MailSenderConfigurationBuilder.class).setReportAsFile(true).setMailTo(getResources().getString(R.string.appEmail)).setSubject(getResources().getString(R.string.crashReportEmailSubject, AppUtil.getAppBuildNo(getApplicationContext()))).setEnabled(true);
ACRABuilder.getPluginConfigurationBuilder(LimiterConfigurationBuilder.class).setEnabled(true);
ACRA.init(getApplication(), ACRABuilder);
// Authentication error, close the app
if(errorCode == BiometricPrompt.ERROR_USER_CANCELED ||
errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) {
finish();
}
}
// Authentication succeeded, continue to app
@Override public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) { super.onAuthenticationSucceeded(result); tinyDB.putBoolean("biometricLifeCycle", true); }
// Authentication failed, close the app
@Override public void onAuthenticationFailed() { super.onAuthenticationFailed(); }
});
BiometricPrompt.PromptInfo biometricPromptBuilder = new BiometricPrompt.PromptInfo.Builder()
.setTitle(getString(R.string.biometricAuthTitle))
.setSubtitle(getString(R.string.biometricAuthSubTitle))
.setNegativeButtonText(getString(R.string.cancelButton)).build();
biometricPrompt.authenticate(biometricPromptBuilder);
}
}
protected abstract int getLayoutResourceId();
}

View File

@ -1,6 +1,5 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@ -19,16 +18,15 @@ import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.gitnex.tea4j.models.Commits;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.CommitsAdapter;
import org.mian.gitnex.clients.AppApiService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCommitsBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.interfaces.ApiInterface;
import org.mian.gitnex.models.Commits;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
@ -41,73 +39,63 @@ import retrofit2.Response;
public class CommitsActivity extends BaseActivity {
final Context ctx = this;
private Context appCtx;
private View.OnClickListener onClickListener;
private TextView noData;
private ProgressBar progressBar;
private String TAG = "CommitsActivity";
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private int pageSize = 1;
private RecyclerView recyclerView;
private List<Commits> commitsList;
private CommitsAdapter adapter;
private ApiInterface api;
private ProgressBar progressLoadMore;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_commits;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
Toolbar toolbar = findViewById(R.id.toolbar);
ActivityCommitsBinding activityCommitsBinding = ActivityCommitsBinding.inflate(getLayoutInflater());
setContentView(activityCommitsBinding.getRoot());
Toolbar toolbar = activityCommitsBinding.toolbar;
setSupportActionBar(toolbar);
TinyDB tinyDb = new TinyDB(appCtx);
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 repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
String branchName = getIntent().getStringExtra("branchName");
TextView toolbar_title = findViewById(R.id.toolbar_title);
TextView toolbar_title = activityCommitsBinding.toolbarTitle;
toolbar_title.setMovementMethod(new ScrollingMovementMethod());
toolbar_title.setText(branchName);
ImageView closeActivity = findViewById(R.id.close);
noData = findViewById(R.id.noDataCommits);
progressLoadMore = findViewById(R.id.progressLoadMore);
progressBar = findViewById(R.id.progress_bar);
SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh);
ImageView closeActivity = activityCommitsBinding.close;
noData = activityCommitsBinding.noDataCommits;
progressLoadMore = activityCommitsBinding.progressLoadMore;
progressBar = activityCommitsBinding.progressBar;
SwipeRefreshLayout swipeRefresh = activityCommitsBinding.pullToRefresh;
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
// if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances)
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12")) {
resultLimit = Constants.resultLimitNewGiteaInstances;
}
recyclerView = findViewById(R.id.recyclerView);
recyclerView = activityCommitsBinding.recyclerView;
commitsList = new ArrayList<>();
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
loadInitial(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName, resultLimit);
loadInitial(Authorization.get(ctx), repoOwner, repoName, branchName, resultLimit);
adapter.notifyDataChanged();
}, 200));
adapter = new CommitsAdapter(ctx, commitsList);
@ -116,23 +104,20 @@ public class CommitsActivity extends BaseActivity {
if(commitsList.size() == resultLimit || pageSize == resultLimit) {
int page = (commitsList.size() + resultLimit) / resultLimit;
loadMore(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, page, branchName, resultLimit);
loadMore(Authorization.get(ctx), repoOwner, repoName, page, branchName, resultLimit);
}
}));
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
recyclerView.setAdapter(adapter);
api = AppApiService.createService(ApiInterface.class, instanceUrl, ctx);
loadInitial(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName, resultLimit);
loadInitial(Authorization.get(ctx), repoOwner, repoName, branchName, resultLimit);
}
private void loadInitial(String token, String repoOwner, String repoName, String branchName, int resultLimit) {
Call<List<Commits>> call = api.getRepositoryCommits(token, repoOwner, repoName, 1, branchName, resultLimit);
Call<List<Commits>> call = RetrofitClient.getApiInterface(ctx).getRepositoryCommits(token, repoOwner, repoName, 1, branchName, resultLimit);
call.enqueue(new Callback<List<Commits>>() {
@ -148,7 +133,6 @@ public class CommitsActivity extends BaseActivity {
commitsList.addAll(response.body());
adapter.notifyDataChanged();
noData.setVisibility(View.GONE);
}
else {
@ -164,7 +148,6 @@ public class CommitsActivity extends BaseActivity {
else {
Log.e(TAG, String.valueOf(response.code()));
}
progressBar.setVisibility(View.GONE);
@ -184,7 +167,7 @@ public class CommitsActivity extends BaseActivity {
progressLoadMore.setVisibility(View.VISIBLE);
Call<List<Commits>> call = api.getRepositoryCommits(token, repoOwner, repoName, page, branchName, resultLimit);
Call<List<Commits>> call = RetrofitClient.getApiInterface(ctx).getRepositoryCommits(token, repoOwner, repoName, page, branchName, resultLimit);
call.enqueue(new Callback<List<Commits>>() {
@ -211,7 +194,6 @@ public class CommitsActivity extends BaseActivity {
else {
Log.e(TAG, String.valueOf(response.code()));
}
progressLoadMore.setVisibility(View.GONE);
@ -255,7 +237,6 @@ public class CommitsActivity extends BaseActivity {
});
return super.onCreateOptionsMenu(menu);
}
private void filter(String text) {
@ -263,7 +244,9 @@ public class CommitsActivity extends BaseActivity {
List<Commits> arr = new ArrayList<>();
for(Commits d : commitsList) {
if(d.getCommit().getMessage().toLowerCase().contains(text) || d.getSha().toLowerCase().contains(text)) {
arr.add(d);
}
}
@ -274,6 +257,7 @@ public class CommitsActivity extends BaseActivity {
private void initCloseListener() {
onClickListener = view -> {
getIntent().removeExtra("branchName");
finish();
};

View File

@ -1,29 +1,28 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.gitnex.tea4j.models.Branches;
import org.gitnex.tea4j.models.DeleteFile;
import org.gitnex.tea4j.models.EditFile;
import org.gitnex.tea4j.models.NewFile;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateFileBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.NetworkStatusObserver;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.DeleteFile;
import org.mian.gitnex.models.EditFile;
import org.mian.gitnex.models.NewFile;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
@ -35,250 +34,190 @@ import retrofit2.Callback;
public class CreateFileActivity extends BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
private Button newFileCreate;
private ActivityCreateFileBinding binding;
public static final int FILE_ACTION_CREATE = 0;
public static final int FILE_ACTION_DELETE = 1;
public static final int FILE_ACTION_EDIT = 2;
private int fileAction = FILE_ACTION_CREATE;
private EditText newFileName;
private EditText newFileContent;
private EditText newFileBranchName;
private EditText newFileCommitMessage;
private AutoCompleteTextView newFileBranchesSpinner;
private String filePath;
private String fileSha;
private int fileAction = 0; // 0 = create, 1 = delete, 2 = edit
final Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
List<Branches> branchesList = new ArrayList<>();
private final List<String> branches = new ArrayList<>();
private String instanceUrl;
private String loginUid;
private String repoOwner;
private String repoName;
private String instanceToken;
private String selectedBranch;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_file;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
binding = ActivityCreateFileBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repoOwner = parts[0];
repoName = parts[1];
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);
TextView toolbarTitle = findViewById(R.id.toolbarTitle);
TextView toolbarTitle = binding.toolbarTitle;
newFileName.requestFocus();
assert imm != null;
imm.showSoftInput(newFileName, InputMethodManager.SHOW_IMPLICIT);
binding.newFileName.requestFocus();
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
assert inputMethodManager != null;
inputMethodManager.showSoftInput(binding.newFileName, InputMethodManager.SHOW_IMPLICIT);
newFileCreate = findViewById(R.id.newFileCreate);
binding.close.setOnClickListener(view -> finish());
binding.newFileContent.setOnTouchListener((touchView, motionEvent) -> {
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", 1) == 1) {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
fileAction = getIntent().getIntExtra("fileAction", 1);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 &&
(motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", FILE_ACTION_DELETE) == FILE_ACTION_DELETE) {
fileAction = getIntent().getIntExtra("fileAction", FILE_ACTION_DELETE);
filePath = getIntent().getStringExtra("filePath");
String fileContents = getIntent().getStringExtra("fileContents");
fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.deleteFileText, filePath));
newFileCreate.setText(R.string.deleteFile);
newFileName.setText(filePath);
newFileName.setEnabled(false);
newFileName.setFocusable(false);
binding.newFileCreate.setText(R.string.deleteFile);
binding.newFileNameLayout.setVisibility(View.GONE);
binding.newFileContentLayout.setVisibility(View.GONE);
newFileContent.setText(fileContents);
newFileContent.setEnabled(false);
newFileContent.setFocusable(false);
}
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", 2) == 2) {
fileAction = getIntent().getIntExtra("fileAction", 2);
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", FILE_ACTION_EDIT) == FILE_ACTION_EDIT) {
fileAction = getIntent().getIntExtra("fileAction", FILE_ACTION_EDIT);
filePath = getIntent().getStringExtra("filePath");
String fileContents = getIntent().getStringExtra("fileContents");
fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.editFileText, filePath));
newFileCreate.setText(R.string.editFile);
newFileName.setText(filePath);
newFileName.setEnabled(false);
newFileName.setFocusable(false);
binding.newFileCreate.setText(R.string.editFile);
binding.newFileName.setText(filePath);
binding.newFileName.setEnabled(false);
binding.newFileName.setFocusable(false);
binding.newFileContent.setText(getIntent().getStringExtra("fileContents"));
newFileContent.setText(fileContents);
}
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
newFileBranchesSpinner = findViewById(R.id.newFileBranchesSpinner);
getBranches(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
getBranches(repoOwner, repoName);
disableProcessButton();
if(!connToInternet) {
NetworkStatusObserver networkStatusObserver = NetworkStatusObserver.getInstance(ctx);
networkStatusObserver.registerNetworkStatusListener(binding.newFileCreate::setEnabled);
newFileCreate.setEnabled(false);
}
else {
newFileCreate.setOnClickListener(createFileListener);
}
binding.newFileCreate.setOnClickListener(v -> processNewFile());
}
private View.OnClickListener createFileListener = v -> processNewFile();
private void processNewFile() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
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) {
String newFileName = binding.newFileName.getText() != null ? binding.newFileName.getText().toString() : "";
String newFileContent = binding.newFileContent.getText() != null ? binding.newFileContent.getText().toString() : "";
String newFileBranchName = binding.newFileBranches.getText() != null ? binding.newFileBranches.getText().toString() : "";
String newFileCommitMessage = binding.newFileCommitMessage.getText() != null ? binding.newFileCommitMessage.getText().toString() : "";
if(!AppUtil.hasNetworkConnection(appCtx)) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newFileName_.equals("") || newFileContent_.equals("") || newFileCommitMessage_.equals("")) {
if(((newFileName.isEmpty() || newFileContent.isEmpty()) && fileAction != FILE_ACTION_DELETE) || newFileCommitMessage.isEmpty()) {
Toasty.error(ctx, getString(R.string.newFileRequiredFields));
return;
}
if(selectedBranch.equals("No branch")) {
if(newFileBranchName_.equals("")) {
Toasty.error(ctx, getString(R.string.newFileRequiredFieldNewBranchName));
return;
}
else {
if(!appUtil.checkStringsWithDash(newFileBranchName_)) {
Toasty.error(ctx, getString(R.string.newFileInvalidBranchName));
return;
}
}
}
if(appUtil.charactersLength(newFileCommitMessage_) > 255) {
if(!AppUtil.checkStringsWithDash(newFileBranchName)) {
Toasty.error(ctx, getString(R.string.newFileInvalidBranchName));
return;
}
if(newFileCommitMessage.length() > 255) {
Toasty.warning(ctx, getString(R.string.newFileCommitMessageError));
}
else {
disableProcessButton();
if(fileAction == 1) {
deleteFile(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, filePath,
newFileBranchName_, newFileCommitMessage_, selectedBranch, fileSha);
}
else if(fileAction == 2) {
editFile(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, filePath,
appUtil.encodeBase64(newFileContent_), newFileBranchName_, newFileCommitMessage_, selectedBranch, fileSha);
}
else {
createNewFile(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, newFileName_,
appUtil.encodeBase64(newFileContent_), newFileBranchName_, newFileCommitMessage_, selectedBranch);
}
return;
}
disableProcessButton();
switch(fileAction) {
case FILE_ACTION_CREATE:
createNewFile(repoOwner, repoName, newFileName, AppUtil.encodeBase64(newFileContent), newFileCommitMessage, newFileBranchName);
break;
case FILE_ACTION_DELETE:
deleteFile(repoOwner, repoName, filePath, newFileCommitMessage, newFileBranchName, fileSha);
break;
case FILE_ACTION_EDIT:
editFile(repoOwner, repoName, filePath, AppUtil.encodeBase64(newFileContent), newFileCommitMessage, newFileBranchName, fileSha);
break;
}
}
private void createNewFile(final String instanceUrl, final String token, String repoOwner, String repoName, String fileName, String fileContent, String fileBranchName, String fileCommitMessage, String currentBranch) {
private void createNewFile(String repoOwner, String repoName, String fileName, String fileContent, String fileCommitMessage, String branchName) {
NewFile createNewFileJsonStr;
if(currentBranch.equals("No branch")) {
createNewFileJsonStr = new NewFile("", fileContent, fileCommitMessage, fileBranchName);
}
else {
createNewFileJsonStr = new NewFile(currentBranch, fileContent, fileCommitMessage, "");
}
NewFile createNewFileJsonStr = branches.contains(branchName) ?
new NewFile(branchName, fileContent, fileCommitMessage, "") :
new NewFile("", fileContent, fileCommitMessage, branchName);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.createNewFile(token, repoOwner, repoName, fileName, createNewFileJsonStr);
.getApiInterface(ctx)
.createNewFile(Authorization.get(ctx), 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) {
switch(response.code()) {
enableProcessButton();
Toasty.success(ctx, getString(R.string.newFileSuccessMessage));
finish();
case 201:
enableProcessButton();
Toasty.success(ctx, getString(R.string.newFileSuccessMessage));
finish();
break;
}
else if(response.code() == 401) {
case 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));
break;
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
case 404:
enableProcessButton();
Toasty.warning(ctx, getString(R.string.apiNotFound));
break;
}
else {
if(response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.orgCreatedError));
}
}
default:
enableProcessButton();
Toasty.error(ctx, getString(R.string.orgCreatedError));
break;
}
}
@Override
@ -286,68 +225,57 @@ public class CreateFileActivity extends BaseActivity {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void deleteFile(final String instanceUrl, final String token, String repoOwner, String repoName, String fileName, String fileBranchName, String fileCommitMessage, String currentBranch, String fileSha) {
private void deleteFile(String repoOwner, String repoName, String fileName, String fileCommitMessage, String branchName, String fileSha) {
String branchName;
DeleteFile deleteFileJsonStr;
if(currentBranch.equals("No branch")) {
branchName = fileBranchName;
deleteFileJsonStr = new DeleteFile("", fileCommitMessage, fileBranchName, fileSha);
}
else {
branchName = currentBranch;
deleteFileJsonStr = new DeleteFile(currentBranch, fileCommitMessage, "", fileSha);
}
DeleteFile deleteFileJsonStr = branches.contains(branchName) ?
new DeleteFile(branchName, fileCommitMessage, "", fileSha) :
new DeleteFile("", fileCommitMessage, branchName, fileSha);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.deleteFile(token, repoOwner, repoName, fileName, deleteFileJsonStr);
.getApiInterface(ctx)
.deleteFile(Authorization.get(ctx), repoOwner, repoName, fileName, deleteFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 200) {
switch(response.code()) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.deleteFileMessage, branchName));
getIntent().removeExtra("filePath");
getIntent().removeExtra("fileSha");
getIntent().removeExtra("fileContents");
finish();
}
else if(response.code() == 401) {
case 200:
enableProcessButton();
Toasty.info(ctx, getString(R.string.deleteFileMessage, tinyDB.getString("repoBranch")));
getIntent().removeExtra("filePath");
getIntent().removeExtra("fileSha");
getIntent().removeExtra("fileContents");
finish();
break;
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) {
case 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));
break;
case 404:
enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound));
}
else {
break;
default:
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
}
break;
}
}
@Override
@ -360,64 +288,52 @@ public class CreateFileActivity extends BaseActivity {
}
private void editFile(final String instanceUrl, final String token, String repoOwner, String repoName, String fileName, String fileContent, String fileBranchName, String fileCommitMessage, String currentBranch, String fileSha) {
private void editFile(String repoOwner, String repoName, String fileName, String fileContent, String fileCommitMessage, String branchName, String fileSha) {
String branchName;
EditFile editFileJsonStr;
if(currentBranch.equals("No branch")) {
branchName = fileBranchName;
editFileJsonStr = new EditFile("", fileCommitMessage, fileBranchName, fileSha, fileContent);
}
else {
branchName = currentBranch;
editFileJsonStr = new EditFile(currentBranch, fileCommitMessage, "", fileSha, fileContent);
}
EditFile editFileJsonStr = branches.contains(branchName) ?
new EditFile(branchName, fileCommitMessage, "", fileSha, fileContent) :
new EditFile("", fileCommitMessage, branchName, fileSha, fileContent);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.editFile(token, repoOwner, repoName, fileName, editFileJsonStr);
.getApiInterface(ctx)
.editFile(Authorization.get(ctx), repoOwner, repoName, fileName, editFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 200) {
switch(response.code()) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.editFileMessage, branchName));
getIntent().removeExtra("filePath");
getIntent().removeExtra("fileSha");
getIntent().removeExtra("fileContents");
tinyDb.putBoolean("fileModified", true);
finish();
}
else if(response.code() == 401) {
case 200:
enableProcessButton();
Toasty.info(ctx, getString(R.string.editFileMessage, branchName));
getIntent().removeExtra("filePath");
getIntent().removeExtra("fileSha");
getIntent().removeExtra("fileContents");
tinyDB.putBoolean("fileModified", true);
finish();
break;
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) {
case 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));
break;
case 404:
enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound));
}
else {
break;
default:
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
}
break;
}
}
@Override
@ -425,68 +341,36 @@ public class CreateFileActivity extends BaseActivity {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void getBranches(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
private void getBranches(String repoOwner, String repoName) {
Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getBranches(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(ctx)
.getBranches(Authorization.get(ctx), 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) {
if(response.code() == 200) {
List<Branches> branchesList_ = response.body();
assert response.body() != null;
for(Branches branch : response.body()) branches.add(branch.getName());
branchesList.add(new Branches("No branch"));
assert branchesList_ != null;
if(branchesList_.size() > 0) {
for (int i = 0; i < branchesList_.size(); i++) {
ArrayAdapter<String> adapter = new ArrayAdapter<>(CreateFileActivity.this, R.layout.list_spinner_items, branches);
Branches data = new Branches(
branchesList_.get(i).getName()
);
branchesList.add(data);
binding.newFileBranches.setAdapter(adapter);
binding.newFileBranches.setText(tinyDB.getString("repoBranch"), false);
}
}
enableProcessButton();
ArrayAdapter<Branches> adapter = new ArrayAdapter<>(CreateFileActivity.this,
R.layout.list_spinner_items, branchesList);
newFileBranchesSpinner.setAdapter(adapter);
enableProcessButton();
newFileBranchesSpinner.setOnItemClickListener ((parent, view, position, id) -> {
selectedBranch = branchesList.get(position).getName();
if(selectedBranch.equals("No branch")) {
newFileBranchName.setEnabled(true);
newFileBranchName.setVisibility(View.VISIBLE);
}
else {
newFileBranchName.setEnabled(false);
newFileBranchName.setVisibility(View.GONE);
newFileBranchName.setText("");
}
});
}
}
}
@Override
@ -498,19 +382,7 @@ public class CreateFileActivity extends BaseActivity {
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void disableProcessButton() {
newFileCreate.setEnabled(false);
}
private void enableProcessButton() {
newFileCreate.setEnabled(true);
}
private void disableProcessButton() { binding.newFileCreate.setEnabled(false); }
private void enableProcessButton() { binding.newFileCreate.setEnabled(true); }
}

View File

@ -1,5 +1,6 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
@ -7,11 +8,16 @@ import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.gitnex.tea4j.models.Collaborators;
import org.gitnex.tea4j.models.CreateIssue;
import org.gitnex.tea4j.models.Labels;
import org.gitnex.tea4j.models.Milestones;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.AssigneesActions;
import org.mian.gitnex.actions.LabelsActions;
@ -24,14 +30,10 @@ import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.CreateIssue;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.Milestones;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
@ -49,19 +51,14 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private CustomLabelsSelectionDialogBinding labelsBinding;
private CustomAssigneesSelectionDialogBinding assigneesBinding;
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private Dialog dialogLabels;
private Dialog dialogAssignees;
private String labelsSetter;
private String assigneesSetter;
private int milestoneId;
private String instanceUrl;
private String loginUid;
private String instanceToken;
private String repoOwner;
private String repoName;
@ -74,45 +71,46 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private List<Collaborators> assigneesList = new ArrayList<>();
private List<String> assigneesListData = new ArrayList<>();
@Override
protected int getLayoutResourceId() {
return R.layout.activity_create_issue;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
viewBinding = ActivityCreateIssueBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
setContentView(viewBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
final String loginFullName = tinyDb.getString("userFullname");
String repoFullName = tinyDb.getString("repoFullName");
loginUid = tinyDB.getString("loginUid");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repoOwner = parts[0];
repoName = parts[1];
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
// require gitea 1.12 or higher
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
resultLimit = Constants.resultLimitNewGiteaInstances;
}
viewBinding.newIssueTitle.requestFocus();
assert imm != null;
imm.showSoftInput(viewBinding.newIssueTitle, InputMethodManager.SHOW_IMPLICIT);
viewBinding.newIssueDescription.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
labelsAdapter = new LabelsListAdapter(labelsList, CreateIssueActivity.this, labelsIds);
assigneesAdapter = new AssigneesListAdapter(ctx, assigneesList, CreateIssueActivity.this, assigneesListData);
@ -123,17 +121,13 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
viewBinding.newIssueLabels.setOnClickListener(this);
viewBinding.newIssueDueDate.setOnClickListener(this);
getMilestones(instanceUrl, instanceToken, repoOwner, repoName, loginUid, resultLimit);
getMilestones(repoOwner, repoName, resultLimit);
disableProcessButton();
viewBinding.newIssueLabels.setOnClickListener(newIssueLabels ->
showLabels()
);
viewBinding.newIssueLabels.setOnClickListener(newIssueLabels -> showLabels());
viewBinding.newIssueAssigneesList.setOnClickListener(newIssueAssigneesList ->
showAssignees()
);
viewBinding.newIssueAssigneesList.setOnClickListener(newIssueAssigneesList -> showAssignees());
if(!connToInternet) {
@ -181,11 +175,10 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
View view = assigneesBinding.getRoot();
dialogAssignees.setContentView(view);
assigneesBinding.cancel.setOnClickListener(assigneesBinding_ ->
dialogAssignees.dismiss()
);
assigneesBinding.cancel.setOnClickListener(assigneesBinding_ -> dialogAssignees.dismiss());
AssigneesActions.getRepositoryAssignees(ctx, instanceUrl, instanceToken, repoOwner, repoName, assigneesList, dialogAssignees, assigneesAdapter, assigneesBinding);
dialogAssignees.show();
AssigneesActions.getRepositoryAssignees(ctx, repoOwner, repoName, assigneesList, dialogAssignees, assigneesAdapter, assigneesBinding);
}
private void showLabels() {
@ -202,11 +195,10 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
View view = labelsBinding.getRoot();
dialogLabels.setContentView(view);
labelsBinding.cancel.setOnClickListener(labelsBinding_ ->
dialogLabels.dismiss()
);
labelsBinding.cancel.setOnClickListener(labelsBinding_ -> dialogLabels.dismiss());
LabelsActions.getRepositoryLabels(ctx, instanceUrl, instanceToken, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
dialogLabels.show();
LabelsActions.getRepositoryLabels(ctx, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
}
private void processNewIssue() {
@ -221,7 +213,6 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (newIssueTitleForm.equals("")) {
@ -240,20 +231,18 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
}
disableProcessButton();
createNewIssueFunc(instanceUrl, instanceToken, repoOwner, repoName, loginUid, newIssueDescriptionForm, newIssueDueDateForm, milestoneId, newIssueTitleForm);
createNewIssueFunc(repoOwner, repoName, loginUid, newIssueDescriptionForm, newIssueDueDateForm, milestoneId, newIssueTitleForm);
}
private void createNewIssueFunc(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String loginUid, String newIssueDescriptionForm, String newIssueDueDateForm, int newIssueMilestoneIdForm, String newIssueTitleForm) {
private void createNewIssueFunc(String repoOwner, String repoName, String loginUid, String newIssueDescriptionForm, String newIssueDueDateForm, int newIssueMilestoneIdForm, String newIssueTitleForm) {
CreateIssue createNewIssueJson = new CreateIssue(loginUid, newIssueDescriptionForm, false, newIssueDueDateForm, newIssueMilestoneIdForm, newIssueTitleForm, assigneesListData, labelsIds);
Call<JsonElement> call3;
call3 = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.createNewIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, createNewIssueJson);
.getApiInterface(ctx)
.createNewIssue(Authorization.get(ctx), repoOwner, repoName, createNewIssueJson);
call3.enqueue(new Callback<JsonElement>() {
@ -262,7 +251,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
if(response2.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
tinyDb.putBoolean("resumeIssues", true);
Toasty.success(ctx, getString(R.string.issueCreated));
@ -300,13 +289,12 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
onClickListener = view -> finish();
}
private void getMilestones(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid, int resultLimit) {
private void getMilestones(String repoOwner, String repoName, int resultLimit) {
String msState = "open";
Call<List<Milestones>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getMilestones(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, 1, resultLimit, msState);
.getApiInterface(ctx)
.getMilestones(Authorization.get(ctx), repoOwner, repoName, 1, resultLimit, msState);
call.enqueue(new Callback<List<Milestones>>() {
@ -314,13 +302,16 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
public void onResponse(@NonNull Call<List<Milestones>> call, @NonNull retrofit2.Response<List<Milestones>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Milestones> milestonesList_ = response.body();
milestonesList.add(new Milestones(0,getString(R.string.issueCreatedNoMilestone)));
assert milestonesList_ != null;
if(milestonesList_.size() > 0) {
for (int i = 0; i < milestonesList_.size(); i++) {
//Don't translate "open" is a enum
@ -331,7 +322,6 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
);
milestonesList.add(data);
}
}
}
@ -375,9 +365,9 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
datePickerDialog.show();
}
else if(v == viewBinding.createNewIssueButton) {
processNewIssue();
}
}
private void disableProcessButton() {

View File

@ -10,21 +10,21 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import com.pes.androidmaterialcolorpickerdialog.ColorPickerCallback;
import org.gitnex.tea4j.models.CreateLabel;
import org.gitnex.tea4j.models.Labels;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateLabelBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.CreateLabel;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.viewmodels.LabelsViewModel;
import org.mian.gitnex.viewmodels.OrganizationLabelsViewModel;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
@ -39,45 +39,37 @@ public class CreateLabelActivity extends BaseActivity {
private TextView colorPicker;
private EditText labelName;
private Button createLabelButton;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_label;
}
private TinyDB tinyDB;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
ActivityCreateLabelBinding activityCreateLabelBinding = ActivityCreateLabelBinding.inflate(getLayoutInflater());
setContentView(activityCreateLabelBinding.getRoot());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
final TinyDB tinyDb = new TinyDB(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
tinyDB = TinyDB.getInstance(appCtx);
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");
if(getIntent().getStringExtra("labelAction") != null && Objects.requireNonNull(getIntent().getStringExtra("labelAction")).equals("delete")) {
deleteLabel(instanceUrl, instanceToken, repoOwner, repoName, Integer.parseInt(Objects.requireNonNull(getIntent().getStringExtra("labelId"))), loginUid);
deleteLabel(repoOwner, repoName, Integer.parseInt(Objects.requireNonNull(getIntent().getStringExtra("labelId"))));
finish();
return;
}
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
ImageView closeActivity = findViewById(R.id.close);
colorPicker = findViewById(R.id.colorPicker);
labelName = findViewById(R.id.labelName);
createLabelButton = findViewById(R.id.createLabelButton);
ImageView closeActivity = activityCreateLabelBinding.close;
colorPicker = activityCreateLabelBinding.colorPicker;
labelName = activityCreateLabelBinding.labelName;
createLabelButton = activityCreateLabelBinding.createLabelButton;
labelName.requestFocus();
assert imm != null;
@ -87,22 +79,14 @@ public class CreateLabelActivity extends BaseActivity {
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
colorPicker.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
cp.show();
}
});
colorPicker.setOnClickListener(v -> cp.show());
cp.setCallback(new ColorPickerCallback() {
@Override
public void onColorChosen(@ColorInt int color) {
cp.setCallback(color -> {
//Log.i("#Hex no alpha", String.format("#%06X", (0xFFFFFF & color)));
colorPicker.setBackgroundColor(color);
tinyDb.putString("labelColor", String.format("#%06X", (0xFFFFFF & color)));
cp.dismiss();
}
//Log.i("#Hex no alpha", String.format("#%06X", (0xFFFFFF & color)));
colorPicker.setBackgroundColor(color);
tinyDB.putString("labelColor", String.format("#%06X", (0xFFFFFF & color)));
cp.dismiss();
});
if(getIntent().getStringExtra("labelAction") != null && Objects.requireNonNull(getIntent().getStringExtra("labelAction")).equals("edit")) {
@ -110,9 +94,9 @@ public class CreateLabelActivity extends BaseActivity {
labelName.setText(getIntent().getStringExtra("labelTitle"));
int labelColor_ = Color.parseColor("#" + getIntent().getStringExtra("labelColor"));
colorPicker.setBackgroundColor(labelColor_);
tinyDb.putString("labelColorDefault", "#" + getIntent().getStringExtra("labelColor"));
tinyDB.putString("labelColorDefault", "#" + getIntent().getStringExtra("labelColor"));
TextView toolbar_title = findViewById(R.id.toolbar_title);
TextView toolbar_title = activityCreateLabelBinding.toolbarTitle;
toolbar_title.setText(getResources().getString(R.string.pageTitleLabelUpdate));
createLabelButton.setText(getResources().getString(R.string.newUpdateButtonCopy));
@ -131,119 +115,112 @@ public class CreateLabelActivity extends BaseActivity {
}
private View.OnClickListener createLabelListener = v -> processCreateLabel();
private final View.OnClickListener createLabelListener = v -> processCreateLabel();
private View.OnClickListener updateLabelListener = v -> processUpdateLabel();
private final View.OnClickListener updateLabelListener = v -> processUpdateLabel();
private void processUpdateLabel() {
final TinyDB tinyDb = new TinyDB(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
String repoFullName = tinyDb.getString("repoFullName");
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");
String updateLabelName = labelName.getText().toString();
String updateLabelColor;
if(tinyDb.getString("labelColor").isEmpty()) {
updateLabelColor = tinyDb.getString("labelColorDefault");
if(tinyDB.getString("labelColor").isEmpty()) {
updateLabelColor = tinyDB.getString("labelColorDefault");
}
else {
updateLabelColor = tinyDb.getString("labelColor");
updateLabelColor = tinyDB.getString("labelColor");
}
if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(updateLabelName.equals("")) {
Toasty.error(ctx, getString(R.string.labelEmptyError));
return;
}
if(!appUtil.checkStrings(updateLabelName)) {
if(!AppUtil.checkStrings(updateLabelName)) {
Toasty.error(ctx, getString(R.string.labelNameError));
return;
}
disableProcessButton();
patchLabel(instanceUrl, instanceToken, repoOwner, repoName, updateLabelName, updateLabelColor, Integer.parseInt(
Objects.requireNonNull(getIntent().getStringExtra("labelId"))), loginUid);
patchLabel(repoOwner, repoName, updateLabelName, updateLabelColor, Integer.parseInt(
Objects.requireNonNull(getIntent().getStringExtra("labelId"))));
}
private void processCreateLabel() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
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");
String newLabelName = labelName.getText().toString();
String newLabelColor;
if(tinyDb.getString("labelColor").isEmpty()) {
if(tinyDB.getString("labelColor").isEmpty()) {
newLabelColor = String.format("#%06X", (0xFFFFFF & ContextCompat.getColor(ctx, R.color.releasePre)));
}
else {
newLabelColor = tinyDb.getString("labelColor");
newLabelColor = tinyDB.getString("labelColor");
}
if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newLabelName.equals("")) {
Toasty.error(ctx, getString(R.string.labelEmptyError));
return;
}
if(!appUtil.checkStrings(newLabelName)) {
if(!AppUtil.checkStrings(newLabelName)) {
Toasty.error(ctx, getString(R.string.labelNameError));
return;
}
disableProcessButton();
createNewLabel(instanceUrl, instanceToken, repoOwner, repoName, newLabelName, newLabelColor, loginUid);
createNewLabel(repoOwner, repoName, newLabelName, newLabelColor);
}
private void createNewLabel(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String newLabelName, String newLabelColor, String loginUid) {
private void createNewLabel(String repoOwner, String repoName, String newLabelName, String newLabelColor) {
CreateLabel createLabelFunc = new CreateLabel(newLabelName, newLabelColor);
final TinyDB tinyDb = new TinyDB(appCtx);
Call<CreateLabel> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.createLabel(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, createLabelFunc);
if(getIntent().getStringExtra("type") != null && Objects.requireNonNull(getIntent().getStringExtra("type")).equals("org")) {
call = RetrofitClient.getApiInterface(ctx).createOrganizationLabel(Authorization.get(ctx), getIntent().getStringExtra("orgName"), createLabelFunc);
}
else {
call = RetrofitClient.getApiInterface(ctx).createLabel(Authorization.get(ctx), repoOwner, repoName, createLabelFunc);
}
call.enqueue(new Callback<CreateLabel>() {
@ -253,10 +230,9 @@ public class CreateLabelActivity extends BaseActivity {
if(response.code() == 201) {
Toasty.success(ctx, getString(R.string.labelCreated));
tinyDb.putString("labelColor", "");
tinyDb.putBoolean("labelsRefresh", true);
tinyDB.putString("labelColor", "");
tinyDB.putBoolean("labelsRefresh", true);
finish();
}
else if(response.code() == 401) {
@ -265,22 +241,19 @@ public class CreateLabelActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
tinyDb.putString("labelColor", "");
tinyDB.putString("labelColor", "");
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<CreateLabel> call, @NonNull Throwable t) {
tinyDb.putString("labelColor", "");
tinyDB.putString("labelColor", "");
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -288,17 +261,20 @@ public class CreateLabelActivity extends BaseActivity {
}
private void patchLabel(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String updateLabelName, String updateLabelColor, int labelId, String loginUid) {
private void patchLabel(String repoOwner, String repoName, String updateLabelName, String updateLabelColor, int labelId) {
CreateLabel createLabelFunc = new CreateLabel(updateLabelName, updateLabelColor);
final TinyDB tinyDb = new TinyDB(appCtx);
Call<CreateLabel> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.patchLabel(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, labelId, createLabelFunc);
if(getIntent().getStringExtra("type") != null && Objects.requireNonNull(getIntent().getStringExtra("type")).equals("org")) {
call = RetrofitClient.getApiInterface(ctx).patchOrganizationLabel(Authorization.get(ctx), getIntent().getStringExtra("orgName"), labelId, createLabelFunc);
}
else {
call = RetrofitClient.getApiInterface(appCtx).patchLabel(Authorization.get(ctx), repoOwner, repoName, labelId, createLabelFunc);
}
call.enqueue(new Callback<CreateLabel>() {
@ -306,18 +282,19 @@ public class CreateLabelActivity extends BaseActivity {
public void onResponse(@NonNull Call<CreateLabel> call, @NonNull retrofit2.Response<CreateLabel> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
Toasty.success(ctx, getString(R.string.labelUpdated));
tinyDb.putString("labelColor", "");
tinyDb.putBoolean("labelsRefresh", true);
tinyDb.putString("labelColorDefault", "");
tinyDB.putString("labelColor", "");
tinyDB.putBoolean("labelsRefresh", true);
tinyDB.putString("labelColorDefault", "");
getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId");
getIntent().removeExtra("labelTitle");
getIntent().removeExtra("labelColor");
getIntent().removeExtra("type");
finish();
}
}
else if(response.code() == 401) {
@ -327,24 +304,21 @@ public class CreateLabelActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
tinyDb.putString("labelColor", "");
tinyDb.putString("labelColorDefault", "");
tinyDB.putString("labelColor", "");
tinyDB.putString("labelColorDefault", "");
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<CreateLabel> call, @NonNull Throwable t) {
tinyDb.putString("labelColor", "");
tinyDb.putString("labelColorDefault", "");
tinyDB.putString("labelColor", "");
tinyDB.putString("labelColorDefault", "");
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -353,26 +327,30 @@ public class CreateLabelActivity extends BaseActivity {
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId");
getIntent().removeExtra("labelTitle");
getIntent().removeExtra("labelColor");
finish();
}
onClickListener = view -> {
getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId");
getIntent().removeExtra("labelTitle");
getIntent().removeExtra("labelColor");
getIntent().removeExtra("type");
finish();
};
}
private void deleteLabel(final String instanceUrl, final String instanceToken, final String repoOwner, final String repoName, int labelId, String loginUid) {
private void deleteLabel(final String repoOwner, final String repoName, int labelId) {
Call<Labels> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.deleteLabel(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, labelId);
if(getIntent().getStringExtra("type") != null && Objects.requireNonNull(getIntent().getStringExtra("type")).equals("org")) {
call = RetrofitClient.getApiInterface(appCtx).deleteOrganizationLabel(Authorization.get(ctx), getIntent().getStringExtra("orgName"), labelId);
}
else {
call = RetrofitClient.getApiInterface(appCtx).deleteLabel(Authorization.get(ctx), repoOwner, repoName, labelId);
}
call.enqueue(new Callback<Labels>() {
@ -380,13 +358,21 @@ public class CreateLabelActivity extends BaseActivity {
public void onResponse(@NonNull Call<Labels> call, @NonNull retrofit2.Response<Labels> response) {
if(response.isSuccessful()) {
if(response.code() == 204) {
Toasty.success(ctx, getString(R.string.labelDeleteText));
LabelsViewModel.loadLabelsList(instanceUrl, instanceToken, repoOwner, repoName, ctx);
if(getIntent().getStringExtra("type") != null && Objects.requireNonNull(getIntent().getStringExtra("type")).equals("org")) {
OrganizationLabelsViewModel.loadOrgLabelsList(Authorization.get(ctx), getIntent().getStringExtra("orgName"), ctx, null, null);
}
else {
LabelsViewModel.loadLabelsList(Authorization.get(ctx), repoOwner, repoName, ctx);
}
getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId");
getIntent().removeExtra("type");
}
}
else if(response.code() == 401) {
@ -395,14 +381,11 @@ public class CreateLabelActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.error(ctx, getString(R.string.labelDeleteErrorText));
}
}
@Override

View File

@ -1,25 +1,27 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.Milestones;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateMilestoneBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Milestones;
import java.util.Calendar;
import retrofit2.Call;
import retrofit2.Callback;
@ -35,34 +37,41 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
private EditText milestoneTitle;
private EditText milestoneDescription;
private Button createNewMilestoneButton;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_milestone;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
ActivityCreateMilestoneBinding activityCreateMilestoneBinding = ActivityCreateMilestoneBinding.inflate(getLayoutInflater());
setContentView(activityCreateMilestoneBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
milestoneDueDate = findViewById(R.id.milestoneDueDate);
ImageView closeActivity = findViewById(R.id.close);
createNewMilestoneButton = findViewById(R.id.createNewMilestoneButton);
milestoneTitle = findViewById(R.id.milestoneTitle);
milestoneDescription = findViewById(R.id.milestoneDescription);
milestoneDueDate = activityCreateMilestoneBinding.milestoneDueDate;
ImageView closeActivity = activityCreateMilestoneBinding.close;
createNewMilestoneButton = activityCreateMilestoneBinding.createNewMilestoneButton;
milestoneTitle = activityCreateMilestoneBinding.milestoneTitle;
milestoneDescription = activityCreateMilestoneBinding.milestoneDescription;
milestoneTitle.requestFocus();
assert imm != null;
imm.showSoftInput(milestoneTitle, InputMethodManager.SHOW_IMPLICIT);
milestoneDescription.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
milestoneDueDate.setOnClickListener(this);
@ -78,21 +87,17 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
}
private View.OnClickListener createMilestoneListener = v -> processNewMilestone();
private final View.OnClickListener createMilestoneListener = v -> processNewMilestone();
private void processNewMilestone() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
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");
//String appLocale = tinyDb.getString("locale");
String newMilestoneTitle = milestoneTitle.getText().toString();
String newMilestoneDescription = milestoneDescription.getText().toString();
@ -102,26 +107,25 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newMilestoneTitle.equals("")) {
Toasty.error(ctx, getString(R.string.milestoneNameErrorEmpty));
return;
}
if(!newMilestoneDescription.equals("")) {
if (appUtil.charactersLength(newMilestoneDescription) > 255) {
if (newMilestoneDescription.length() > 255) {
Toasty.warning(ctx, getString(R.string.milestoneDescError));
return;
}
}
String finalMilestoneDueDate = null;
if(!newMilestoneDueDate.isEmpty()) {
finalMilestoneDueDate = (AppUtil.customDateCombine(AppUtil.customDateFormat(newMilestoneDueDate)));
@ -134,19 +138,17 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
}
disableProcessButton();
createNewMilestone(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, newMilestoneTitle, newMilestoneDescription, finalMilestoneDueDate);
createNewMilestone(Authorization.get(ctx), repoOwner, repoName, newMilestoneTitle, newMilestoneDescription, finalMilestoneDueDate);
}
private void createNewMilestone(final String instanceUrl, final String token, String repoOwner, String repoName, String newMilestoneTitle, String newMilestoneDescription, String newMilestoneDueDate) {
private void createNewMilestone(final String token, String repoOwner, String repoName, String newMilestoneTitle, String newMilestoneDescription, String newMilestoneDueDate) {
Milestones createMilestone = new Milestones(newMilestoneDescription, newMilestoneTitle, newMilestoneDueDate);
Call<Milestones> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(appCtx)
.createMilestone(token, repoOwner, repoName, createMilestone);
call.enqueue(new Callback<Milestones>() {
@ -155,14 +157,14 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
public void onResponse(@NonNull Call<Milestones> call, @NonNull retrofit2.Response<Milestones> response) {
if(response.isSuccessful()) {
if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
tinyDb.putBoolean("milestoneCreated", true);
Toasty.success(ctx, getString(R.string.milestoneCreated));
enableProcessButton();
finish();
}
}
else if(response.code() == 401) {
@ -172,19 +174,17 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.milestoneCreatedError));
}
}
@Override
public void onFailure(@NonNull Call<Milestones> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -203,16 +203,7 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
final int mDay = c.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(this,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
milestoneDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth));
}
}, mYear, mMonth, mDay);
(view, year, monthOfYear, dayOfMonth) -> milestoneDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth)), mYear, mMonth, mDay);
datePickerDialog.show();
}

View File

@ -10,14 +10,14 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateNewUserBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserInfo;
import retrofit2.Call;
import retrofit2.Callback;
@ -33,30 +33,25 @@ public class CreateNewUserActivity extends BaseActivity {
private EditText userEmail;
private EditText userPassword;
private Button createUserButton;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_new_user;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
ActivityCreateNewUserBinding activityCreateNewUserBinding = ActivityCreateNewUserBinding.inflate(getLayoutInflater());
setContentView(activityCreateNewUserBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
ImageView closeActivity = findViewById(R.id.close);
createUserButton = findViewById(R.id.createUserButton);
fullName = findViewById(R.id.fullName);
userUserName = findViewById(R.id.userUserName);
userEmail = findViewById(R.id.userEmail);
userPassword = findViewById(R.id.userPassword);
ImageView closeActivity = activityCreateNewUserBinding.close;
createUserButton = activityCreateNewUserBinding.createUserButton;
fullName = activityCreateNewUserBinding.fullName;
userUserName = activityCreateNewUserBinding.userUserName;
userEmail = activityCreateNewUserBinding.userEmail;
userPassword = activityCreateNewUserBinding.userPassword;
fullName.requestFocus();
assert imm != null;
@ -73,17 +68,11 @@ public class CreateNewUserActivity extends BaseActivity {
createUserButton.setOnClickListener(createNewUserListener);
}
}
private void processCreateNewUser() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String newFullName = fullName.getText().toString().trim();
String newUserName = userUserName.getText().toString().trim();
@ -94,51 +83,44 @@ public class CreateNewUserActivity extends BaseActivity {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newFullName.equals("") || newUserName.equals("") | newUserEmail.equals("") || newUserPassword.equals("")) {
Toasty.error(ctx, getString(R.string.emptyFields));
return;
}
if(!appUtil.checkStrings(newFullName)) {
if(!AppUtil.checkStrings(newFullName)) {
Toasty.error(ctx, getString(R.string.userInvalidFullName));
return;
}
if(!appUtil.checkStringsWithAlphaNumeric(newUserName)) {
if(!AppUtil.checkStringsWithAlphaNumeric(newUserName)) {
Toasty.error(ctx, getString(R.string.userInvalidUserName));
return;
}
if(!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) {
Toasty.error(ctx, getString(R.string.userInvalidEmail));
return;
}
disableProcessButton();
createNewUser(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), newFullName, newUserName, newUserEmail, newUserPassword);
createNewUser(Authorization.get(ctx), newFullName, newUserName, newUserEmail, newUserPassword);
}
private void createNewUser(final String instanceUrl, final String instanceToken, String newFullName, String newUserName, String newUserEmail, String newUserPassword) {
private void createNewUser(final String instanceToken, String newFullName, String newUserName, String newUserEmail, String newUserPassword) {
UserInfo createUser = new UserInfo(newUserEmail, newFullName, newUserName, newUserPassword, newUserName, 0, true);
Call<UserInfo> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(appCtx)
.createNewUser(instanceToken, createUser);
call.enqueue(new Callback<UserInfo>() {
@ -151,7 +133,6 @@ public class CreateNewUserActivity extends BaseActivity {
Toasty.success(ctx, getString(R.string.userCreatedText));
enableProcessButton();
finish();
}
else if(response.code() == 401) {
@ -160,33 +141,27 @@ public class CreateNewUserActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else if(response.code() == 422) {
enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.userExistsError));
}
else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
@ -199,7 +174,7 @@ public class CreateNewUserActivity extends BaseActivity {
}
private View.OnClickListener createNewUserListener = v -> processCreateNewUser();
private final View.OnClickListener createNewUserListener = v -> processCreateNewUser();
private void initCloseListener() {

View File

@ -1,22 +1,25 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.UserOrganizations;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateOrganizationBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserOrganizations;
import retrofit2.Call;
import retrofit2.Callback;
@ -32,36 +35,43 @@ public class CreateOrganizationActivity extends BaseActivity {
private EditText orgName;
private EditText orgDesc;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_organization;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
ActivityCreateOrganizationBinding activityCreateOrganizationBinding = ActivityCreateOrganizationBinding.inflate(getLayoutInflater());
setContentView(activityCreateOrganizationBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
closeActivity = findViewById(R.id.close);
orgName = findViewById(R.id.newOrganizationName);
orgDesc = findViewById(R.id.newOrganizationDescription);
closeActivity = activityCreateOrganizationBinding.close;
orgName = activityCreateOrganizationBinding.newOrganizationName;
orgDesc = activityCreateOrganizationBinding.newOrganizationDescription;
orgName.requestFocus();
assert imm != null;
imm.showSoftInput(orgName, InputMethodManager.SHOW_IMPLICIT);
orgDesc.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
createOrganizationButton = findViewById(R.id.createNewOrganizationButton);
createOrganizationButton = activityCreateOrganizationBinding.createNewOrganizationButton;
if(!connToInternet) {
@ -75,28 +85,15 @@ public class CreateOrganizationActivity extends BaseActivity {
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
private View.OnClickListener createOrgListener = new View.OnClickListener() {
public void onClick(View v) {
processNewOrganization();
}
};
private final View.OnClickListener createOrgListener = v -> processNewOrganization();
private void processNewOrganization() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String newOrgName = orgName.getText().toString();
String newOrgDesc = orgDesc.getText().toString();
@ -105,44 +102,39 @@ public class CreateOrganizationActivity extends BaseActivity {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(!newOrgDesc.equals("")) {
if (appUtil.charactersLength(newOrgDesc) > 255) {
if (newOrgDesc.length() > 255) {
Toasty.warning(ctx, getString(R.string.orgDescError));
return;
}
}
if(newOrgName.equals("")) {
Toasty.error(ctx, getString(R.string.orgNameErrorEmpty));
}
else if(!appUtil.checkStrings(newOrgName)) {
else if(!AppUtil.checkStrings(newOrgName)) {
Toasty.warning(ctx, getString(R.string.orgNameErrorInvalid));
}
else {
disableProcessButton();
createNewOrganization(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), newOrgName, newOrgDesc);
createNewOrganization(Authorization.get(ctx), newOrgName, newOrgDesc);
}
}
private void createNewOrganization(final String instanceUrl, final String token, String orgName, String orgDesc) {
private void createNewOrganization(final String token, String orgName, String orgDesc) {
UserOrganizations createOrganization = new UserOrganizations(orgName, null, orgDesc, null, null);
Call<UserOrganizations> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(appCtx)
.createNewOrganization(token, createOrganization);
call.enqueue(new Callback<UserOrganizations>() {
@ -152,12 +144,11 @@ public class CreateOrganizationActivity extends BaseActivity {
if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
tinyDb.putBoolean("orgCreated", true);
enableProcessButton();
Toasty.success(ctx, getString(R.string.orgCreated));
finish();
}
else if(response.code() == 401) {
@ -166,37 +157,35 @@ public class CreateOrganizationActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 409) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.orgExistsError));
}
else if(response.code() == 422) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.orgExistsError));
}
else {
if(response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.orgCreatedError));
}
}
}
@Override
public void onFailure(@NonNull Call<UserOrganizations> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}

View File

@ -1,16 +1,21 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.Branches;
import org.gitnex.tea4j.models.CreatePullRequest;
import org.gitnex.tea4j.models.Labels;
import org.gitnex.tea4j.models.Milestones;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.LabelsActions;
import org.mian.gitnex.adapters.LabelsListAdapter;
@ -19,18 +24,12 @@ import org.mian.gitnex.databinding.ActivityCreatePrBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.CreatePullRequest;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.Milestones;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
@ -41,19 +40,15 @@ import retrofit2.Callback;
public class CreatePullRequestActivity extends BaseActivity implements LabelsListAdapter.LabelsListAdapterListener {
private View.OnClickListener onClickListener;
private Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
private ActivityCreatePrBinding viewBinding;
private CustomLabelsSelectionDialogBinding labelsBinding;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private Dialog dialogLabels;
private String labelsSetter;
private List<Integer> labelsIds = new ArrayList<>();
private List<String> assignees = new ArrayList<>();
private int milestoneId;
private String instanceUrl;
private String loginUid;
private String instanceToken;
private String repoOwner;
@ -65,38 +60,39 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
List<Branches> branchesList = new ArrayList<>();
List<Labels> labelsList = new ArrayList<>();
public CreatePullRequestActivity() {
}
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_pr;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
viewBinding = ActivityCreatePrBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
setContentView(viewBinding.getRoot());
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
loginUid = tinyDB.getString("loginUid");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repoOwner = parts[0];
repoName = parts[1];
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
// require gitea 1.12 or higher
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = Constants.resultLimitNewGiteaInstances;
}
viewBinding.prBody.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
labelsAdapter = new LabelsListAdapter(labelsList, CreatePullRequestActivity.this, labelsIds);
ImageView closeActivity = findViewById(R.id.close);
@ -110,16 +106,12 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
disableProcessButton();
getMilestones(instanceUrl, instanceToken, repoOwner, repoName, loginUid, resultLimit);
getBranches(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
getMilestones(repoOwner, repoName, resultLimit);
getBranches(repoOwner, repoName);
viewBinding.prLabels.setOnClickListener(prLabels ->
showLabels()
);
viewBinding.prLabels.setOnClickListener(prLabels -> showLabels());
viewBinding.createPr.setOnClickListener(createPr ->
processPullRequest()
);
viewBinding.createPr.setOnClickListener(createPr -> processPullRequest());
}
private void processPullRequest() {
@ -133,13 +125,16 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
assignees.add("");
if (labelsIds.size() == 0) {
labelsIds.add(0);
}
if (dueDate.matches("")) {
dueDate = null;
}
else {
dueDate = AppUtil.customDateCombine(AppUtil.customDateFormat(dueDate));
}
@ -160,24 +155,23 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
Toasty.error(ctx, getString(R.string.sameBranchesError));
}
else {
createPullRequest(prTitle, prDescription, mergeInto, pullFrom, milestoneId, dueDate, assignees);
}
//Log.e("processPullRequest", String.valueOf(milestoneId));
}
private void createPullRequest(String prTitle, String prDescription, String mergeInto, String pullFrom, int milestoneId, String dueDate, List<String> assignees) {
CreatePullRequest createPullRequest = new CreatePullRequest(prTitle, prDescription, loginUid, mergeInto, pullFrom, milestoneId, dueDate, assignees, labelsIds);
Call<ResponseBody> transferCall = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
Call<Void> transferCall = RetrofitClient
.getApiInterface(appCtx)
.createPullRequest(instanceToken, repoOwner, repoName, createPullRequest);
transferCall.enqueue(new Callback<ResponseBody>() {
transferCall.enqueue(new Callback<Void>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
public void onResponse(@NonNull Call<Void> call, @NonNull retrofit2.Response<Void> response) {
disableProcessButton();
@ -201,11 +195,10 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericServerResponseError));
@ -231,6 +224,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
dialogLabels = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogLabels.getWindow() != null) {
dialogLabels.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
@ -239,19 +233,17 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
View view = labelsBinding.getRoot();
dialogLabels.setContentView(view);
labelsBinding.cancel.setOnClickListener(editProperties ->
dialogLabels.dismiss()
);
labelsBinding.cancel.setOnClickListener(editProperties -> dialogLabels.dismiss());
LabelsActions.getRepositoryLabels(ctx, instanceUrl, instanceToken, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
dialogLabels.show();
LabelsActions.getRepositoryLabels(ctx, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
}
private void getBranches(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
private void getBranches(String repoOwner, String repoName) {
Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getBranches(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(ctx)
.getBranches(Authorization.get(ctx), repoOwner, repoName);
call.enqueue(new Callback<List<Branches>>() {
@ -259,19 +251,18 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
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();
assert branchesList_ != null;
if(branchesList_.size() > 0) {
for (int i = 0; i < branchesList_.size(); i++) {
Branches data = new Branches(
branchesList_.get(i).getName()
);
Branches data = new Branches(branchesList_.get(i).getName());
branchesList.add(data);
}
}
@ -296,13 +287,12 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
}
private void getMilestones(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid, int resultLimit) {
private void getMilestones(String repoOwner, String repoName, int resultLimit) {
String msState = "open";
Call<List<Milestones>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getMilestones(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, 1, resultLimit, msState);
.getApiInterface(appCtx)
.getMilestones(Authorization.get(ctx), repoOwner, repoName, 1, resultLimit, msState);
call.enqueue(new Callback<List<Milestones>>() {
@ -315,7 +305,9 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
milestonesList.add(new Milestones(0,getString(R.string.issueCreatedNoMilestone)));
assert milestonesList_ != null;
if(milestonesList_.size() > 0) {
for (int i = 0; i < milestonesList_.size(); i++) {
//Don't translate "open" is a enum
@ -326,7 +318,6 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
);
milestonesList.add(data);
}
}
}

View File

@ -1,8 +1,10 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
@ -12,15 +14,15 @@ import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.Branches;
import org.gitnex.tea4j.models.Releases;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateReleaseBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.Releases;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
@ -41,61 +43,60 @@ public class CreateReleaseActivity extends BaseActivity {
private CheckBox releaseType;
private CheckBox releaseDraft;
private Button createNewRelease;
final Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
private String selectedBranch;
private String instanceUrl;
private String loginUid;
private String instanceToken;
private String repoOwner;
private String repoName;
List<Branches> branchesList = new ArrayList<>();
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_release;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
ActivityCreateReleaseBinding activityCreateReleaseBinding = ActivityCreateReleaseBinding.inflate(getLayoutInflater());
setContentView(activityCreateReleaseBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repoOwner = parts[0];
repoName = parts[1];
closeActivity = findViewById(R.id.close);
releaseTagName = findViewById(R.id.releaseTagName);
releaseTitle = findViewById(R.id.releaseTitle);
releaseContent = findViewById(R.id.releaseContent);
releaseType = findViewById(R.id.releaseType);
releaseDraft = findViewById(R.id.releaseDraft);
closeActivity = activityCreateReleaseBinding.close;
releaseTagName = activityCreateReleaseBinding.releaseTagName;
releaseTitle = activityCreateReleaseBinding.releaseTitle;
releaseContent = activityCreateReleaseBinding.releaseContent;
releaseType = activityCreateReleaseBinding.releaseType;
releaseDraft = activityCreateReleaseBinding.releaseDraft;
releaseTitle.requestFocus();
assert imm != null;
imm.showSoftInput(releaseTitle, InputMethodManager.SHOW_IMPLICIT);
releaseContent.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
releaseBranch = findViewById(R.id.releaseBranch);
getBranches(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
releaseBranch = activityCreateReleaseBinding.releaseBranch;
getBranches(Authorization.get(ctx), repoOwner, repoName);
createNewRelease = findViewById(R.id.createNewRelease);
createNewRelease = activityCreateReleaseBinding.createNewRelease;
disableProcessButton();
if(!connToInternet) {
@ -109,7 +110,7 @@ public class CreateReleaseActivity extends BaseActivity {
}
private View.OnClickListener createReleaseListener = v -> processNewRelease();
private final View.OnClickListener createReleaseListener = v -> processNewRelease();
private void processNewRelease() {
@ -126,7 +127,6 @@ public class CreateReleaseActivity extends BaseActivity {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newReleaseTitle.equals("")) {
@ -148,19 +148,17 @@ public class CreateReleaseActivity extends BaseActivity {
}
disableProcessButton();
createNewReleaseFunc(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, newReleaseTagName, newReleaseTitle, newReleaseContent, selectedBranch, newReleaseType, newReleaseDraft);
createNewReleaseFunc(Authorization.get(ctx), repoOwner, repoName, newReleaseTagName, newReleaseTitle, newReleaseContent, selectedBranch, newReleaseType, newReleaseDraft);
}
private void createNewReleaseFunc(final String instanceUrl, final String token, String repoOwner, String repoName, String newReleaseTagName, String newReleaseTitle, String newReleaseContent, String selectedBranch, boolean newReleaseType, boolean newReleaseDraft) {
private void createNewReleaseFunc(final String token, String repoOwner, String repoName, String newReleaseTagName, String newReleaseTitle, String newReleaseContent, String selectedBranch, boolean newReleaseType, boolean newReleaseDraft) {
Releases createReleaseJson = new Releases(newReleaseContent, newReleaseDraft, newReleaseTitle, newReleaseType, newReleaseTagName, selectedBranch);
Call<Releases> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.createNewRelease(token, repoOwner, repoName, createReleaseJson);
call.enqueue(new Callback<Releases>() {
@ -170,7 +168,7 @@ public class CreateReleaseActivity extends BaseActivity {
if (response.code() == 201) {
tinyDb.putBoolean("updateReleases", true);
tinyDB.putBoolean("updateReleases", true);
Toasty.success(ctx, getString(R.string.releaseCreatedText));
enableProcessButton();
finish();
@ -182,27 +180,22 @@ public class CreateReleaseActivity extends BaseActivity {
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}
@Override
@ -215,11 +208,10 @@ public class CreateReleaseActivity extends BaseActivity {
}
private void getBranches(String instanceUrl, String instanceToken, final String repoOwner, final String repoName) {
private void getBranches(String instanceToken, final String repoOwner, final String repoName) {
Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.getBranches(instanceToken, repoOwner, repoName);
call.enqueue(new Callback<List<Branches>>() {
@ -228,6 +220,7 @@ public class CreateReleaseActivity extends BaseActivity {
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();
@ -256,7 +249,6 @@ public class CreateReleaseActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
}

View File

@ -14,15 +14,16 @@ import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.OrgOwner;
import org.gitnex.tea4j.models.OrganizationRepository;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateRepoBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.OrgOwner;
import org.mian.gitnex.models.OrganizationRepository;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -43,14 +44,9 @@ public class CreateRepoActivity extends BaseActivity {
private EditText repoName;
private EditText repoDesc;
private CheckBox repoAccess;
final Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
private String instanceUrl;
private String loginUid;
private String userLogin;
private String instanceToken;
private String selectedOwner;
@ -60,31 +56,25 @@ public class CreateRepoActivity extends BaseActivity {
final List<String> reservedRepoNames = Arrays.asList(".", "..");
final Pattern reservedRepoPatterns = Pattern.compile("\\.(git|wiki)$");
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_repo;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
ActivityCreateRepoBinding activityCreateRepoBinding = ActivityCreateRepoBinding.inflate(getLayoutInflater());
setContentView(activityCreateRepoBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(ctx);
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
userLogin = tinyDb.getString("userLogin");
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
loginUid = tinyDB.getString("loginUid");
userLogin = tinyDB.getString("userLogin");
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
closeActivity = findViewById(R.id.close);
repoName = findViewById(R.id.newRepoName);
repoDesc = findViewById(R.id.newRepoDescription);
repoAccess = findViewById(R.id.newRepoPrivate);
closeActivity = activityCreateRepoBinding.close;
repoName = activityCreateRepoBinding.newRepoName;
repoDesc = activityCreateRepoBinding.newRepoDescription;
repoAccess = activityCreateRepoBinding.newRepoPrivate;
repoName.requestFocus();
assert imm != null;
@ -93,10 +83,10 @@ public class CreateRepoActivity extends BaseActivity {
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
spinner = findViewById(R.id.ownerSpinner);
getOrganizations(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), userLogin);
spinner = activityCreateRepoBinding.ownerSpinner;
getOrganizations(Authorization.get(ctx), userLogin);
createRepo = findViewById(R.id.createNewRepoButton);
createRepo = activityCreateRepoBinding.createNewRepoButton;
disableProcessButton();
if(!connToInternet) {
@ -109,12 +99,11 @@ public class CreateRepoActivity extends BaseActivity {
}
}
private View.OnClickListener createRepoListener = v -> processNewRepo();
private final View.OnClickListener createRepoListener = v -> processNewRepo();
private void processNewRepo() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
String newRepoName = repoName.getText().toString();
String newRepoDesc = repoDesc.getText().toString();
@ -127,7 +116,8 @@ public class CreateRepoActivity extends BaseActivity {
}
if(!newRepoDesc.equals("")) {
if (appUtil.charactersLength(newRepoDesc) > 255) {
if (newRepoDesc.length() > 255) {
Toasty.warning(ctx, getString(R.string.repoDescError));
return;
@ -138,7 +128,7 @@ public class CreateRepoActivity extends BaseActivity {
Toasty.error(ctx, getString(R.string.repoNameErrorEmpty));
}
else if(!appUtil.checkStrings(newRepoName)) {
else if(!AppUtil.checkStrings(newRepoName)) {
Toasty.warning(ctx, getString(R.string.repoNameErrorInvalid));
}
@ -157,11 +147,11 @@ public class CreateRepoActivity extends BaseActivity {
else {
disableProcessButton();
createNewRepository(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), loginUid, newRepoName, newRepoDesc, selectedOwner, newRepoAccess);
createNewRepository(Authorization.get(ctx), loginUid, newRepoName, newRepoDesc, selectedOwner, newRepoAccess);
}
}
private void createNewRepository(final String instanceUrl, final String token, String loginUid, String repoName, String repoDesc, String selectedOwner, boolean isPrivate) {
private void createNewRepository(final String token, String loginUid, String repoName, String repoDesc, String selectedOwner, boolean isPrivate) {
OrganizationRepository createRepository = new OrganizationRepository(true, repoDesc, null, null, repoName, isPrivate, "Default");
@ -169,15 +159,13 @@ public class CreateRepoActivity extends BaseActivity {
if(selectedOwner.equals(loginUid)) {
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.createNewUserRepository(token, createRepository);
}
else {
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.createNewUserOrgRepository(token, selectedOwner, createRepository);
}
@ -188,7 +176,7 @@ public class CreateRepoActivity extends BaseActivity {
if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
tinyDb.putBoolean("repoCreated", true);
Toasty.success(ctx, getString(R.string.repoCreated));
enableProcessButton();
@ -212,7 +200,6 @@ public class CreateRepoActivity extends BaseActivity {
enableProcessButton();
Toasty.error(ctx, getString(R.string.repoCreatedError));
}
}
@Override
@ -224,12 +211,11 @@ public class CreateRepoActivity extends BaseActivity {
});
}
private void getOrganizations(String instanceUrl, String instanceToken, final String userLogin) {
private void getOrganizations(String instanceToken, final String userLogin) {
Call<List<OrgOwner>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getOrgOwners(instanceToken);
.getApiInterface(ctx)
.getOrgOwners(instanceToken, 1, 50);
call.enqueue(new Callback<List<OrgOwner>>() {
@ -244,20 +230,20 @@ public class CreateRepoActivity extends BaseActivity {
organizationsList.add(new OrgOwner(userLogin));
assert organizationsList_ != null;
if(organizationsList_.size() > 0) {
for(int i = 0; i < organizationsList_.size(); i++) {
if(!tinyDb.getString("organizationId").isEmpty()) {
if(!tinyDB.getString("organizationId").isEmpty()) {
if(Integer.parseInt(tinyDb.getString("organizationId")) == organizationsList_.get(i).getId()) {
if(Integer.parseInt(tinyDB.getString("organizationId")) == organizationsList_.get(i).getId()) {
organizationId = i + 1;
}
}
OrgOwner data = new OrgOwner(organizationsList_.get(i).getUsername());
organizationsList.add(data);
}
}
@ -267,7 +253,7 @@ public class CreateRepoActivity extends BaseActivity {
spinner.setOnItemClickListener ((parent, view, position, id) -> selectedOwner = organizationsList.get(position).getUsername());
if(tinyDb.getBoolean("organizationAction") & organizationId != 0) {
if(tinyDB.getBoolean("organizationAction") & organizationId != 0) {
int selectOwnerById = organizationId;
new Handler(Looper.getMainLooper()).postDelayed(() -> {
@ -276,7 +262,7 @@ public class CreateRepoActivity extends BaseActivity {
selectedOwner = organizationsList.get(selectOwnerById).getUsername();
}, 500);
tinyDb.putBoolean("organizationAction", false);
tinyDB.putBoolean("organizationAction", false);
}
enableProcessButton();

View File

@ -11,14 +11,16 @@ import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.res.ResourcesCompat;
import org.gitnex.tea4j.models.Teams;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateTeamByOrgBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Teams;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -31,8 +33,6 @@ import retrofit2.Callback;
public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClickListener {
final Context ctx = CreateTeamByOrgActivity.this;
private Context appCtx;
private View.OnClickListener onClickListener;
private TextView teamName;
private TextView teamDesc;
@ -41,15 +41,10 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
private TextView teamAccessControls;
private TextView teamAccessControlsArray;
private Button createTeamButton;
private String[] permissionList = {"Read", "Write", "Admin"};
private final 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[] {
private final String[] accessControlsList = new String[] {
"Code",
"Issues",
"Pull Request",
@ -61,7 +56,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
private List<String> pushAccessList;
private boolean[] selectedAccessControlsTrueFalse = new boolean[]{
private final boolean[] selectedAccessControlsTrueFalse = new boolean[]{
false,
false,
false,
@ -75,20 +70,22 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
ActivityCreateTeamByOrgBinding activityCreateTeamByOrgBinding = ActivityCreateTeamByOrgBinding.inflate(getLayoutInflater());
setContentView(activityCreateTeamByOrgBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
ImageView closeActivity = findViewById(R.id.close);
teamName = findViewById(R.id.teamName);
teamDesc = findViewById(R.id.teamDesc);
teamPermission = findViewById(R.id.teamPermission);
teamPermissionDetail = findViewById(R.id.teamPermissionDetail);
teamAccessControls = findViewById(R.id.teamAccessControls);
teamAccessControlsArray = findViewById(R.id.teamAccessControlsArray);
createTeamButton = findViewById(R.id.createTeamButton);
ImageView closeActivity = activityCreateTeamByOrgBinding.close;
teamName = activityCreateTeamByOrgBinding.teamName;
teamDesc = activityCreateTeamByOrgBinding.teamDesc;
teamPermission = activityCreateTeamByOrgBinding.teamPermission;
teamPermissionDetail = activityCreateTeamByOrgBinding.teamPermissionDetail;
teamAccessControls = activityCreateTeamByOrgBinding.teamAccessControls;
teamAccessControlsArray = activityCreateTeamByOrgBinding.teamAccessControlsArray;
createTeamButton = activityCreateTeamByOrgBinding.createTeamButton;
teamName.requestFocus();
assert imm != null;
@ -102,12 +99,8 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx);
pBuilder.setTitle(R.string.newTeamPermission);
if(permissionSelectedChoice != -1) {
pBuilder.setCancelable(true);
}
else {
pBuilder.setCancelable(false);
}
pBuilder.setCancelable(permissionSelectedChoice != -1);
pBuilder.setSingleChoiceItems(permissionList, permissionSelectedChoice, (dialogInterface, i) -> {
permissionSelectedChoice = i;
@ -136,15 +129,12 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
}
dialogInterface.dismiss();
});
AlertDialog pDialog = pBuilder.create();
pDialog.show();
});
teamAccessControls.setOnClickListener(v -> {
teamAccessControls.setText("");
@ -189,6 +179,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
}
if(value){
teamAccessControls.setText(getString(R.string.newTeamPermissionValues, teamAccessControls.getText(), pushAccessList.get(selectedVal)));
teamAccessControlsArray.setText(getString(R.string.newTeamPermissionValuesFinal, teamAccessControlsArray.getText(), repoCode));
}
@ -198,15 +189,16 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
String data = String.valueOf(teamAccessControls.getText());
if(!data.equals("")) {
teamAccessControls.setText(data.substring(0, data.length() - 2));
}
String dataArray = String.valueOf(teamAccessControlsArray.getText());
if(!dataArray.equals("")) {
teamAccessControlsArray.setText(dataArray.substring(0, dataArray.length() - 2));
}
//Log.i("orgName", String.valueOf(teamAccessControlsArray.getText()));
});
AlertDialog aDialog = aDialogBuilder.create();
@ -218,25 +210,21 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
if(!connToInternet) {
createTeamButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius(8);
shape.setColor(ResourcesCompat.getColor(getResources(), R.color.hintColor, null));
createTeamButton.setBackground(shape);
} else {
}
else {
createTeamButton.setEnabled(true);
createTeamButton.setOnClickListener(this);
}
}
private void processCreateTeam() {
AppUtil appUtil = new AppUtil();
final TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final String orgName = tinyDb.getString("orgName");;
@ -251,64 +239,60 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (newTeamName.equals("")) {
Toasty.error(ctx, getString(R.string.teamNameEmpty));
return;
}
if(!appUtil.checkStringsWithAlphaNumericDashDotUnderscore(newTeamName)) {
if(!AppUtil.checkStringsWithAlphaNumericDashDotUnderscore(newTeamName)) {
Toasty.warning(ctx, getString(R.string.teamNameError));
return;
}
if(!newTeamDesc.equals("")) {
if(!appUtil.checkStrings(newTeamDesc)) {
if(!AppUtil.checkStrings(newTeamDesc)) {
Toasty.warning(ctx, getString(R.string.teamDescError));
return;
}
if(newTeamDesc.length() > 100) {
Toasty.warning(ctx, getString(R.string.teamDescLimit));
return;
}
}
if (newTeamPermission.equals("")) {
Toasty.error(ctx, getString(R.string.teamPermissionEmpty));
return;
}
List<String> newTeamAccessControls_ = new ArrayList<>(Arrays.asList(newTeamAccessControls.split(",")));
for (int i = 0; i < newTeamAccessControls_.size(); i++) {
newTeamAccessControls_.set(i, newTeamAccessControls_.get(i).trim());
}
createNewTeamCall(instanceUrl, instanceToken, orgName, newTeamName, newTeamDesc, newTeamPermission, newTeamAccessControls_, loginUid);
createNewTeamCall(instanceToken, orgName, newTeamName, newTeamDesc, newTeamPermission, newTeamAccessControls_, loginUid);
}
private void createNewTeamCall(final String instanceUrl, final String instanceToken, String orgName, String newTeamName, String newTeamDesc, String newTeamPermission, List<String> newTeamAccessControls, String loginUid) {
private void createNewTeamCall(final String instanceToken, String orgName, String newTeamName, String newTeamDesc, String newTeamPermission, List<String> newTeamAccessControls, String loginUid) {
Teams createNewTeamJson = new Teams(newTeamName, newTeamDesc, newTeamPermission, newTeamAccessControls);
Call<Teams> call3;
call3 = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.createTeamsByOrg(Authorization.returnAuthentication(ctx, loginUid, instanceToken), orgName, createNewTeamJson);
.getApiInterface(ctx)
.createTeamsByOrg(Authorization.get(ctx), orgName, createNewTeamJson);
call3.enqueue(new Callback<Teams>() {
@ -316,15 +300,15 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
public void onResponse(@NonNull Call<Teams> call, @NonNull retrofit2.Response<Teams> response2) {
if(response2.isSuccessful()) {
if(response2.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
tinyDb.putBoolean("resumeTeams", true);
Toasty.success(ctx, getString(R.string.teamCreated));
finish();
}
}
else if(response2.code() == 404) {
@ -341,7 +325,6 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
Toasty.error(ctx, getString(R.string.teamCreatedError));
}
}
@Override
@ -356,6 +339,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
public void onClick(View v) {
if(v == createTeamButton) {
processCreateTeam();
}
}

View File

@ -1,6 +1,5 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@ -10,26 +9,31 @@ import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.gitnex.tea4j.models.Files;
import org.gitnex.tea4j.models.Organization;
import org.gitnex.tea4j.models.PullRequests;
import org.gitnex.tea4j.models.UserInfo;
import org.gitnex.tea4j.models.UserRepositories;
import org.jetbrains.annotations.NotNull;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.databinding.ActivityDeeplinksBinding;
import org.mian.gitnex.helpers.PathsHelper;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.models.PullRequests;
import org.mian.gitnex.models.UserRepositories;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import io.mikael.urlbuilder.UrlBuilder;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -38,309 +42,333 @@ import retrofit2.Callback;
public class DeepLinksActivity extends BaseActivity {
private ActivityDeeplinksBinding viewBinding;
private Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
private String currentInstance;
private String instanceToken;
private boolean accountFound = false;
private Intent mainIntent;
private Intent issueIntent;
private Intent repoIntent;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_deeplinks;
}
private Intent orgIntent;
private Intent userIntent;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
viewBinding = ActivityDeeplinksBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
setContentView(viewBinding.getRoot());
mainIntent = new Intent(ctx, MainActivity.class);
issueIntent = new Intent(ctx, IssueDetailActivity.class);
repoIntent = new Intent(ctx, RepoDetailActivity.class);
orgIntent = new Intent(ctx, OrganizationDetailActivity.class);
userIntent = new Intent(ctx, ProfileActivity.class);
Intent intent = getIntent();
Uri data = intent.getData();
assert data != null;
// check for login
if(!tinyDb.getBoolean("loggedInMode")) {
if(!tinyDB.getBoolean("loggedInMode")) {
Intent loginIntent = new Intent(ctx, LoginActivity.class);
loginIntent.putExtra("instanceUrl", data.getHost());
ctx.startActivity(loginIntent);
finish();
ctx.startActivity(new Intent(ctx, LoginActivity.class));
}
// check for the links(URI) to be in the db
UserAccountsApi userAccountsApi = new UserAccountsApi(ctx);
UserAccountsApi userAccountsApi = BaseApi.getInstance(ctx, UserAccountsApi.class);
List<UserAccount> userAccounts = userAccountsApi.usersAccounts();
if(userAccounts.size() > 0) {
for(UserAccount userAccount : userAccounts) {
String hostUri;
for(int i = 0; i < userAccounts.size(); i++) {
String hostUri = userAccount.getInstanceUrl();
hostUri = userAccounts.get(i).getInstanceUrl();
currentInstance = userAccount.getInstanceUrl();
instanceToken = userAccount.getToken();
currentInstance = userAccounts.get(i).getInstanceUrl();
instanceToken = userAccounts.get(i).getToken();
if(hostUri.toLowerCase().contains(Objects.requireNonNull(data.getHost().toLowerCase()))) {
if(!hostUri.contains(Objects.requireNonNull(data.getHost()))) {
accountFound = true;
AppUtil.switchToAccount(ctx, userAccount);
break;
// check for valid instance
checkInstance(data);
return;
}
}
}
// redirect to proper fragment/activity, If no action is there, show options where user to want to go like repos, profile, notifications etc
if(data.getPathSegments().size() > 0) {
viewBinding.progressBar.setVisibility(View.GONE);
String[] restOfUrl = Objects.requireNonNull(data.getPath()).split("/");
if(data.getPathSegments().contains("issues")) { // issue
if(!Objects.requireNonNull(data.getLastPathSegment()).contains("issues") & StringUtils.isNumeric(data.getLastPathSegment())) {
issueIntent.putExtra("issueNumber", data.getLastPathSegment());
tinyDb.putString("issueNumber", data.getLastPathSegment());
tinyDb.putString("issueType", "Issue");
tinyDb.putString("repoFullName", restOfUrl[restOfUrl.length - 4] + "/" + restOfUrl[restOfUrl.length - 3]);
final String repoOwner = restOfUrl[restOfUrl.length - 4];
final String repoName = restOfUrl[restOfUrl.length - 3];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository dataRepo = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", dataRepo.getRepositoryId());
}
ctx.startActivity(issueIntent);
finish();
}
else if(Objects.requireNonNull(data.getLastPathSegment()).contains("issues")) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 3], restOfUrl[restOfUrl.length - 2], "issue");
}, 500);
}
else {
ctx.startActivity(mainIntent);
finish();
}
}
else if(data.getPathSegments().contains("pulls")) { // pr
if(!Objects.requireNonNull(data.getLastPathSegment()).contains("pulls") & StringUtils.isNumeric(data.getLastPathSegment())) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
getPullRequest(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 4], restOfUrl[restOfUrl.length - 3],
Integer.parseInt(data.getLastPathSegment()));
}, 500);
}
else if(Objects.requireNonNull(data.getLastPathSegment()).contains("pulls")) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 3], restOfUrl[restOfUrl.length - 2], "pull");
}, 500);
}
else {
ctx.startActivity(mainIntent);
finish();
}
}
else if(!restOfUrl[restOfUrl.length - 2].equals("") & !restOfUrl[restOfUrl.length - 1].equals("")) { // go to repo
new Handler(Looper.getMainLooper()).postDelayed(() -> {
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 2], restOfUrl[restOfUrl.length - 1], "repo");
}, 500);
}
else { // no action, show options
if(tinyDb.getInt("defaultScreenId") == 1) { // repos
mainIntent.putExtra("launchFragmentByLinkHandler", "repos");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDb.getInt("defaultScreenId") == 2) { // org
mainIntent.putExtra("launchFragmentByLinkHandler", "org");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDb.getInt("defaultScreenId") == 3) { // notifications
if(accountFound) {
// redirect to proper fragment/activity, if no action is there, show options where user to want to go like repos, profile, notifications etc
if(data.getPathSegments().size() == 1) {
if(data.getLastPathSegment().equals("notifications")) { // notifications
mainIntent.putExtra("launchFragmentByLinkHandler", "notification");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDb.getInt("defaultScreenId") == 4) { // explore
else if(data.getLastPathSegment().equals("explore")) { // explore
mainIntent.putExtra("launchFragmentByLinkHandler", "explore");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDb.getInt("defaultScreenId") == 0) { // show options
viewBinding.noActionFrame.setVisibility(View.VISIBLE);
viewBinding.addNewAccountFrame.setVisibility(View.GONE);
viewBinding.repository.setOnClickListener(repository -> {
tinyDb.putInt("defaultScreenId", 1);
tinyDb.putString("defaultScreenStr", getResources().getString(R.string.navRepos));
mainIntent.putExtra("launchFragmentByLinkHandler", "repos");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.organization.setOnClickListener(organization -> {
tinyDb.putInt("defaultScreenId", 2);
tinyDb.putString("defaultScreenStr", getResources().getString(R.string.navOrgs));
mainIntent.putExtra("launchFragmentByLinkHandler", "org");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.notification.setOnClickListener(notification -> {
tinyDb.putInt("defaultScreenId", 3);
tinyDb.putString("defaultScreenStr", getResources().getString(R.string.pageTitleNotifications));
mainIntent.putExtra("launchFragmentByLinkHandler", "notification");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.explore.setOnClickListener(explore -> {
tinyDb.putInt("defaultScreenId", 4);
tinyDb.putString("defaultScreenStr", getResources().getString(R.string.navExplore));
mainIntent.putExtra("launchFragmentByLinkHandler", "explore");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.launchApp2.setOnClickListener(launchApp2 -> {
tinyDb.putInt("defaultScreenId", 0);
tinyDb.putString("defaultScreenStr", getResources().getString(R.string.generalDeepLinkSelectedText));
ctx.startActivity(mainIntent);
finish();
});
else if(data.getLastPathSegment().equals(tinyDB.getString("userLogin"))) { // your user profile
mainIntent.putExtra("launchFragmentByLinkHandler", "profile");
ctx.startActivity(mainIntent);
finish();
}
else if(data.getLastPathSegment().equals("admin")) {
mainIntent.putExtra("launchFragmentByLinkHandler", "admin");
ctx.startActivity(mainIntent);
finish();
}
else {
new Handler(Looper.getMainLooper()).postDelayed(() ->
getUserOrOrg(currentInstance, instanceToken, data.getLastPathSegment()), 500);
}
}
}
else {
ctx.startActivity(mainIntent);
finish();
}
}
private void checkInstance(Uri data) {
URI host;
if(data.getPort() > 0) {
host = UrlBuilder.fromString(UrlHelper.fixScheme(data.getHost(), "https")).withPort(data.getPort()).toUri();
}
else {
host = UrlBuilder.fromString(UrlHelper.fixScheme(data.getHost(), "https")).toUri();
}
URI instanceUrl = UrlBuilder.fromUri(host).withScheme(data.getScheme().toLowerCase()).withPath(PathsHelper.join(host.getPath(), "/api/v1/"))
.toUri();
Call<GiteaVersion> callVersion;
callVersion = RetrofitClient.getInstance(String.valueOf(instanceUrl), ctx).getApiInterface().getGiteaVersion();
callVersion.enqueue(new Callback<GiteaVersion>() {
@Override
public void onResponse(@NonNull final Call<GiteaVersion> callVersion, @NonNull retrofit2.Response<GiteaVersion> responseVersion) {
if(responseVersion.isSuccessful() || responseVersion.code() == 403) {
viewBinding.progressBar.setVisibility(View.GONE);
viewBinding.addNewAccountFrame.setVisibility(View.VISIBLE);
viewBinding.noActionFrame.setVisibility(View.GONE);
viewBinding.addAccountText.setText(String.format(getResources().getString(R.string.accountDoesNotExist), data.getHost()));
viewBinding.addNewAccount.setOnClickListener(addNewAccount -> {
Intent accountIntent = new Intent(ctx, AddNewAccountActivity.class);
startActivity(accountIntent);
finish();
});
viewBinding.openInBrowser.setOnClickListener(addNewAccount -> {
Intent intentBrowser = new Intent();
intentBrowser.setAction(Intent.ACTION_VIEW);
intentBrowser.addCategory(Intent.CATEGORY_BROWSABLE);
intentBrowser.setData(Uri.parse(String.valueOf(host)));
startActivity(intentBrowser);
finish();
});
viewBinding.launchApp.setOnClickListener(launchApp -> {
startActivity(mainIntent);
finish();
});
else if(data.getPathSegments().size() == 2) {
if(data.getPathSegments().get(0).equals("explore")) { // specific explore tab
if(data.getPathSegments().get(1).equals("organizations")) { // orgs
mainIntent.putExtra("exploreOrgs", true);
}
mainIntent.putExtra("launchFragmentByLinkHandler", "explore");
ctx.startActivity(mainIntent);
finish();
}
else if(data.getPathSegments().get(0).equals("user") && data.getPathSegments().get(1).equals("login")) { // open login
Intent loginIntent = new Intent(ctx, AddNewAccountActivity.class);
loginIntent.putExtra("instanceUrl", data.getHost());
loginIntent.putExtra("instanceProtocol", data.getScheme());
ctx.startActivity(loginIntent);
finish();
}
else if(data.getPathSegments().get(0).equals("admin")) {
mainIntent.putExtra("launchFragmentByLinkHandler", "admin");
mainIntent.putExtra("giteaAdminAction", data.getLastPathSegment());
ctx.startActivity(mainIntent);
finish();
}
else if(!data.getPathSegments().get(0).equals("") & !data.getLastPathSegment().equals("")) { // go to repo
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getLastPathSegment(), "repo"), 500);
}
else { // no action, show options
showNoActionButtons();
}
}
else if(data.getPathSegments().size() >= 3) {
if(data.getPathSegments().get(2).equals("issues")) { // issue
@Override
public void onFailure(@NonNull Call<GiteaVersion> callVersion, @NonNull Throwable t) {
if(!Objects.requireNonNull(data.getLastPathSegment()).contains("issues") & StringUtils.isNumeric(data.getLastPathSegment())) {
Toasty.error(ctx, getResources().getString(R.string.versionUnknown));
issueIntent.putExtra("issueNumber", data.getLastPathSegment());
issueIntent.putExtra("openedFromLink", "true");
String[] urlSplitted = data.toString().split("#");
if (urlSplitted.length == 2) {
issueIntent.putExtra("issueComment", urlSplitted[1]);
}
tinyDB.putString("issueNumber", data.getLastPathSegment());
tinyDB.putString("issueType", "Issue");
tinyDB.putString("repoFullName", data.getPathSegments().get(0) + "/" + data.getPathSegments().get(1));
final String repoOwner = data.getPathSegments().get(0);
final String repoName = data.getPathSegments().get(1);
int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = BaseApi.getInstance(ctx, RepositoriesApi.class);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDB.putLong("repositoryId", id);
}
else {
Repository dataRepo = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDB.putLong("repositoryId", dataRepo.getRepositoryId());
}
ctx.startActivity(issueIntent);
finish();
}
else if(Objects.requireNonNull(data.getLastPathSegment()).contains("issues")) {
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "issue"), 500);
}
else if(data.getLastPathSegment().equals("new")) {
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "issueNew"), 500);
}
else {
ctx.startActivity(mainIntent);
finish();
}
}
else if(data.getPathSegments().get(2).equals("pulls")) { // pr
if(!Objects.requireNonNull(data.getLastPathSegment()).contains("pulls") & StringUtils.isNumeric(data.getLastPathSegment())) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
String[] urlSplitted = data.toString().split("#");
if (urlSplitted.length == 2) {
issueIntent.putExtra("issueComment", urlSplitted[1]);
}
getPullRequest(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), Integer.parseInt(data.getLastPathSegment()));
}, 500);
}
else if(Objects.requireNonNull(data.getLastPathSegment()).contains("pulls")) {
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "pull"), 500);
}
else if(data.getLastPathSegment().equals("files")) { // pr diff
new Handler(Looper.getMainLooper()).postDelayed(() -> {
issueIntent.putExtra("openPrDiff", "true");
getPullRequest(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), Integer.parseInt(data.getPathSegments().get(3)));
}, 500);
}
else {
ctx.startActivity(mainIntent);
finish();
}
}
else if(data.getPathSegments().get(2).equals("compare")) { // new pull request
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "pullNew"), 500);
}
else if(data.getPathSegments().get(2).equals("commit")) { // commits (no API yet to properly implement)
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "pull"), 500);
}
else if(data.getPathSegments().get(2).equals("commits")) { // commits list
String branch = data.getLastPathSegment();
repoIntent.putExtra("branchName", branch);
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "commitsList"), 500);
}
else if(data.getPathSegments().get(2).equals("milestones") && data.getLastPathSegment().equals("new")) { // new milestone
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "milestonesNew"), 500);
}
else if(data.getPathSegments().get(2).equals("milestones")) { // milestones
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "milestones"), 500);
}
else if(data.getPathSegments().get(2).equals("milestone")) { // milestone
repoIntent.putExtra("milestoneId", data.getLastPathSegment());
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "milestones"), 500);
}
else if(data.getPathSegments().get(2).equals("releases") && data.getLastPathSegment().equals("new")) { // new release
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "newRelease"), 500);
}
else if(data.getPathSegments().get(2).equals("releases")) { // releases
if(data.getPathSegments().size() == 5) {
if(data.getPathSegments().get(2).equals("releases") && data.getPathSegments().get(3).equals("tag")) {
repoIntent.putExtra("releaseTagName", data.getLastPathSegment());
}
}
new Handler(Looper.getMainLooper()).postDelayed(
() -> goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1),
"releases"), 500);
}
else if(data.getPathSegments().get(2).equals("labels")) { // labels
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "labels"), 500);
}
else if(data.getPathSegments().get(2).equals("settings")) { // repo settings
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "settings"), 500);
}
else if(data.getLastPathSegment().equals("branches")) { // branches list
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "branchesList"), 500);
}
else if(data.getPathSegments().size() == 5 && data.getPathSegments().get(2).equals("src") && data.getPathSegments().get(3).equals("branch")) { // branch
repoIntent.putExtra("selectedBranch", data.getLastPathSegment());
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "branch"), 500);
}
else if(data.getPathSegments().get(2).equals("src") && data.getPathSegments().get(3).equals("branch")) { // file/dir
StringBuilder filePath = new StringBuilder();
ArrayList<String> segments = new ArrayList<>(data.getPathSegments());
segments.subList(0, 5).clear();
for (String item : segments) {
filePath.append(item);
filePath.append("/");
}
filePath.deleteCharAt(filePath.toString().length() - 1);
new Handler(Looper.getMainLooper()).postDelayed(() ->
getFile(currentInstance, instanceToken, data.getPathSegments().get(0),
data.getPathSegments().get(1), filePath.toString(), data.getPathSegments().get(4)), 500);
}
else { // no action, show options
showNoActionButtons();
}
}
else {
startActivity(mainIntent);
finish();
}
});
}
else {
viewBinding.progressBar.setVisibility(View.GONE);
viewBinding.addNewAccountFrame.setVisibility(View.VISIBLE);
viewBinding.noActionFrame.setVisibility(View.GONE);
viewBinding.addAccountText.setText(String.format(getResources().getString(R.string.accountDoesNotExist), data.getHost()));
viewBinding.addNewAccount.setOnClickListener(addNewAccount -> {
Intent accountIntent = new Intent(ctx, AddNewAccountActivity.class);
accountIntent.putExtra("instanceUrl", data.getHost());
startActivity(accountIntent);
finish();
});
viewBinding.openInBrowser.setOnClickListener(addNewAccount -> {
Integer port = data.getPort() >= 0 ? data.getPort() : null;
URI host = UrlBuilder.fromString(UrlHelper.fixScheme(data.getHost(), "https"))
.withPort(port)
.toUri();
Intent intentBrowser = new Intent();
intentBrowser.setAction(Intent.ACTION_VIEW);
intentBrowser.addCategory(Intent.CATEGORY_BROWSABLE);
intentBrowser.setData(Uri.parse(String.valueOf(host)));
startActivity(intentBrowser);
finish();
});
viewBinding.launchApp.setOnClickListener(launchApp -> {
startActivity(mainIntent);
finish();
});
}
}
private void getPullRequest(String url, String token, String repoOwner, String repoName, int index) {
Call<PullRequests> call = RetrofitClient
.getInstance(url, ctx)
.getApiInterface()
.getApiInterface(ctx, url)
.getPullRequestByIndex(token, repoOwner, repoName, index);
call.enqueue(new Callback<PullRequests>() {
@ -356,45 +384,46 @@ public class DeepLinksActivity extends BaseActivity {
issueIntent.putExtra("issueNumber", index);
issueIntent.putExtra("prMergeable", prInfo.isMergeable());
issueIntent.putExtra("openedFromLink", "true");
if(prInfo.getHead() != null) {
issueIntent.putExtra("prHeadBranch", prInfo.getHead().getRef());
tinyDb.putString("prHeadBranch", prInfo.getHead().getRef());
tinyDB.putString("prHeadBranch", prInfo.getHead().getRef());
if(prInfo.getHead().getRepo() != null) {
tinyDb.putString("prIsFork", String.valueOf(prInfo.getHead().getRepo().isFork()));
tinyDb.putString("prForkFullName", prInfo.getHead().getRepo().getFull_name());
tinyDB.putString("prIsFork", String.valueOf(prInfo.getHead().getRepo().isFork()));
tinyDB.putString("prForkFullName", prInfo.getHead().getRepo().getFull_name());
}
else {
// pull was done from a deleted fork
tinyDb.putString("prIsFork", "true");
tinyDb.putString("prForkFullName", ctx.getString(R.string.prDeletedFrok));
tinyDB.putString("prIsFork", "true");
tinyDB.putString("prForkFullName", ctx.getString(R.string.prDeletedFork));
}
}
tinyDb.putString("issueNumber", String.valueOf(index));
tinyDb.putString("prMergeable", String.valueOf(prInfo.isMergeable()));
tinyDb.putString("issueType", "Pull");
tinyDB.putString("issueNumber", String.valueOf(index));
tinyDB.putString("prMergeable", String.valueOf(prInfo.isMergeable()));
tinyDB.putString("issueType", "Pull");
tinyDb.putString("repoFullName", repoOwner + "/" + repoName);
tinyDB.putString("repoFullName", repoOwner + "/" + repoName);
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx);
int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = BaseApi.getInstance(ctx, RepositoriesApi.class);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
tinyDB.putLong("repositoryId", id);
}
else {
Repository dataRepo = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", dataRepo.getRepositoryId());
tinyDB.putLong("repositoryId", dataRepo.getRepositoryId());
}
ctx.startActivity(issueIntent);
@ -403,6 +432,8 @@ public class DeepLinksActivity extends BaseActivity {
else {
ctx.startActivity(issueIntent);
finish();
Log.e("onFailure-links-pr", String.valueOf(response.code()));
}
}
@ -410,6 +441,8 @@ public class DeepLinksActivity extends BaseActivity {
@Override
public void onFailure(@NonNull Call<PullRequests> call, @NonNull Throwable t) {
ctx.startActivity(issueIntent);
finish();
Log.e("onFailure-links-pr", t.toString());
}
});
@ -418,8 +451,7 @@ public class DeepLinksActivity extends BaseActivity {
private void goToRepoSection(String url, String token, String repoOwner, String repoName, String type) {
Call<UserRepositories> call = RetrofitClient
.getInstance(url, ctx)
.getApiInterface()
.getApiInterface(ctx, url)
.getUserRepository(token, repoOwner, repoName);
call.enqueue(new Callback<UserRepositories>() {
@ -437,32 +469,32 @@ public class DeepLinksActivity extends BaseActivity {
repoIntent.putExtra("goToSection", "yes");
repoIntent.putExtra("goToSectionType", type);
tinyDb.putString("repoFullName", repoInfo.getFullName());
tinyDB.putString("repoFullName", repoInfo.getFullName());
if(repoInfo.getPrivateFlag()) {
tinyDb.putString("repoType", getResources().getString(R.string.strPrivate));
tinyDB.putString("repoType", getResources().getString(R.string.strPrivate));
}
else {
tinyDb.putString("repoType", getResources().getString(R.string.strPublic));
tinyDB.putString("repoType", getResources().getString(R.string.strPublic));
}
tinyDb.putBoolean("isRepoAdmin", repoInfo.getPermissions().isAdmin());
tinyDb.putString("repoBranch", repoInfo.getDefault_branch());
tinyDB.putBoolean("isRepoAdmin", repoInfo.getPermissions().isAdmin());
tinyDB.putString("repoBranch", repoInfo.getDefault_branch());
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx);
int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = BaseApi.getInstance(ctx, RepositoriesApi.class);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
tinyDB.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
tinyDB.putLong("repositoryId", data.getRepositoryId());
}
ctx.startActivity(repoIntent);
@ -471,7 +503,9 @@ public class DeepLinksActivity extends BaseActivity {
else {
Log.e("onFailure-links", String.valueOf(response.code()));
ctx.startActivity(mainIntent);
finish();
Log.e("onFailure-goToRepo", String.valueOf(response.code()));
}
}
@ -479,8 +513,187 @@ public class DeepLinksActivity extends BaseActivity {
@Override
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) {
Log.e("onFailure-links", t.toString());
ctx.startActivity(mainIntent);
finish();
Log.e("onFailure-goToRepo", t.toString());
}
});
}
private void getUserOrOrg(String url, String instanceToken, String userOrgName) {
Call<Organization> call = RetrofitClient.getApiInterface(ctx, url).getOrganization(instanceToken, userOrgName);
call.enqueue(new Callback<Organization>() {
@Override
public void onResponse(@NotNull Call<Organization> call, @NotNull Response<Organization> response) {
if(response.code() == 404) { // org doesn't exist or it's a user user
Log.d("getUserOrOrg-404", String.valueOf(response.code()));
getUser(url, instanceToken, userOrgName);
}
else if(response.code() == 200) { // org
assert response.body() != null;
orgIntent.putExtra("orgName", response.body().getUsername());
TinyDB tinyDb = TinyDB.getInstance(ctx);
tinyDb.putString("orgName", response.body().getUsername());
tinyDb.putString("organizationId", String.valueOf(response.body().getId()));
tinyDb.putBoolean("organizationAction", true);
ctx.startActivity(orgIntent);
finish();
}
else {
Log.e("getUserOrOrg-code", String.valueOf(response.code()));
ctx.startActivity(mainIntent);
finish();
}
}
@Override
public void onFailure(@NotNull Call<Organization> call, @NotNull Throwable t) {
Log.e("onFailure-getUserOrOrg", t.toString());
}
});
}
private void getUser(String url, String instanceToken, String userName) {
Call<UserInfo> call = RetrofitClient.getApiInterface(ctx, url).getUserProfile(instanceToken, userName);
call.enqueue(new Callback<UserInfo>() {
@Override
public void onResponse(@NotNull Call<UserInfo> call, @NotNull Response<UserInfo> response) {
if(response.code() == 200) {
assert response.body() != null;
userIntent.putExtra("username", response.body().getLogin());
ctx.startActivity(userIntent);
}
else {
Log.e("getUser-code", String.valueOf(response.code()));
ctx.startActivity(mainIntent);
}
finish();
}
@Override
public void onFailure(@NotNull Call<UserInfo> call, @NotNull Throwable t) {
Log.e("onFailure-getUser", t.toString());
ctx.startActivity(mainIntent);
finish();
}
});
}
private void getFile(String url, String instanceToken, String owner, String repo, String filePath, String branch) {
Call<Files> call = RetrofitClient.getApiInterface(ctx, url).getSingleFileContents(instanceToken, owner, repo, filePath, branch);
call.enqueue(new Callback<Files>() {
@Override
public void onResponse(@NotNull Call<Files> call, @NotNull Response<Files> response) {
if(response.code() == 200) {
// check if file and open file/dir
Files file = response.body();
assert file != null;
if(file.getType().equals("file")) {
repoIntent.putExtra("file", file);
repoIntent.putExtra("branch", branch);
goToRepoSection(url, instanceToken, owner, repo, "file");
}
}
else {
Log.e("getFile-onFailure", String.valueOf(response.code()));
ctx.startActivity(mainIntent);
finish();
}
}
@Override
public void onFailure(@NotNull Call<Files> call, @NotNull Throwable t) {
Log.e("getFile-onFailure", t.toString());
// maybe it's a directory
getDir(url, instanceToken, owner, repo, filePath, branch);
}
});
}
private void getDir(String url, String instanceToken, String owner, String repo, String filePath, String branch) {
repoIntent.putExtra("branch", branch);
repoIntent.putExtra("dir", filePath);
goToRepoSection(url, instanceToken, owner, repo, "dir");
}
private void showNoActionButtons() {
viewBinding.progressBar.setVisibility(View.GONE);
if(tinyDB.getInt("defaultScreenId") == 1) { // repos
mainIntent.putExtra("launchFragmentByLinkHandler", "repos");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDB.getInt("defaultScreenId") == 2) { // org
mainIntent.putExtra("launchFragmentByLinkHandler", "org");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDB.getInt("defaultScreenId") == 3) { // notifications
mainIntent.putExtra("launchFragmentByLinkHandler", "notification");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDB.getInt("defaultScreenId") == 4) { // explore
mainIntent.putExtra("launchFragmentByLinkHandler", "explore");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDB.getInt("defaultScreenId") == 0) { // show options
viewBinding.noActionFrame.setVisibility(View.VISIBLE);
viewBinding.addNewAccountFrame.setVisibility(View.GONE);
viewBinding.repository.setOnClickListener(repository -> {
tinyDB.putInt("defaultScreenId", 1);
mainIntent.putExtra("launchFragmentByLinkHandler", "repos");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.organization.setOnClickListener(organization -> {
tinyDB.putInt("defaultScreenId", 2);
mainIntent.putExtra("launchFragmentByLinkHandler", "org");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.notification.setOnClickListener(notification -> {
tinyDB.putInt("defaultScreenId", 3);
mainIntent.putExtra("launchFragmentByLinkHandler", "notification");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.explore.setOnClickListener(explore -> {
tinyDB.putInt("defaultScreenId", 4);
mainIntent.putExtra("launchFragmentByLinkHandler", "explore");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.launchApp2.setOnClickListener(launchApp2 -> {
tinyDB.putInt("defaultScreenId", 0);
ctx.startActivity(mainIntent);
finish();
});
}
}
}

View File

@ -7,6 +7,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
@ -17,18 +18,18 @@ import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.gitnex.tea4j.models.CreateIssue;
import org.gitnex.tea4j.models.Issues;
import org.gitnex.tea4j.models.Milestones;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityEditIssueBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.CreateIssue;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.Milestones;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -43,11 +44,8 @@ import retrofit2.Callback;
public class EditIssueActivity extends BaseActivity implements View.OnClickListener {
final Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
private View.OnClickListener onClickListener;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private EditText editIssueTitle;
private EditText editIssueDescription;
@ -60,52 +58,59 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
List<Milestones> milestonesList = new ArrayList<>();
private String instanceUrl;
private String loginUid;
private String instanceToken;
private String repoOwner;
private String repoName;
private int issueIndex;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_edit_issue;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
ActivityEditIssueBinding activityEditIssueBinding = ActivityEditIssueBinding.inflate(getLayoutInflater());
setContentView(activityEditIssueBinding.getRoot());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
loginUid = tinyDB.getString("loginUid");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repoOwner = parts[0];
repoName = parts[1];
issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
issueIndex = Integer.parseInt(tinyDB.getString("issueNumber"));
ImageView closeActivity = findViewById(R.id.close);
editIssueButton = findViewById(R.id.editIssueButton);
TextView toolbar_title = findViewById(R.id.toolbar_title);
editIssueTitle = findViewById(R.id.editIssueTitle);
editIssueDescription = findViewById(R.id.editIssueDescription);
editIssueDueDate = findViewById(R.id.editIssueDueDate);
ImageView closeActivity = activityEditIssueBinding.close;
editIssueButton = activityEditIssueBinding.editIssueButton;
TextView toolbar_title = activityEditIssueBinding.toolbarTitle;
editIssueTitle = activityEditIssueBinding.editIssueTitle;
editIssueDescription = activityEditIssueBinding.editIssueDescription;
editIssueDueDate = activityEditIssueBinding.editIssueDueDate;
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = Constants.resultLimitNewGiteaInstances;
}
editIssueTitle.requestFocus();
assert imm != null;
imm.showSoftInput(editIssueTitle, InputMethodManager.SHOW_IMPLICIT);
editIssueDescription.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
editIssueMilestoneSpinner = findViewById(R.id.editIssueMilestoneSpinner);
initCloseListener();
@ -114,18 +119,20 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
editIssueDueDate.setOnClickListener(this);
editIssueButton.setOnClickListener(this);
if(!tinyDb.getString("issueNumber").isEmpty()) {
if(!tinyDB.getString("issueNumber").isEmpty()) {
if(tinyDB.getString("issueType").equalsIgnoreCase("Pull")) {
if(tinyDb.getString("issueType").equalsIgnoreCase("Pull")) {
toolbar_title.setText(getString(R.string.editPrNavHeader, String.valueOf(issueIndex)));
}
else {
toolbar_title.setText(getString(R.string.editIssueNavHeader, String.valueOf(issueIndex)));
}
}
disableProcessButton();
getIssue(instanceUrl, instanceToken, loginUid, repoOwner, repoName, issueIndex, resultLimit);
getIssue(instanceToken, loginUid, repoOwner, repoName, issueIndex, resultLimit);
}
private void initCloseListener() {
@ -145,35 +152,34 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (editIssueTitleForm.equals("")) {
Toasty.error(ctx, getString(R.string.issueTitleEmpty));
return;
}
if (editIssueDueDateForm.equals("")) {
editIssueDueDateForm = null;
} else {
}
else {
editIssueDueDateForm = (AppUtil.customDateCombine(AppUtil.customDateFormat(editIssueDueDateForm)));
}
disableProcessButton();
editIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid, editIssueTitleForm, editIssueDescriptionForm, editIssueDueDateForm, milestoneId);
editIssue(instanceToken, repoOwner, repoName, issueIndex, loginUid, editIssueTitleForm, editIssueDescriptionForm, editIssueDueDateForm, milestoneId);
}
private void editIssue(String instanceUrl, String instanceToken, String repoOwner, String repoName, int issueIndex, String loginUid, String title, String description, String dueDate, int milestoneId) {
private void editIssue(String instanceToken, String repoOwner, String repoName, int issueIndex, String loginUid, String title, String description, String dueDate, int milestoneId) {
CreateIssue issueData = new CreateIssue(title, description, dueDate, milestoneId);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.patchIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueData);
.getApiInterface(ctx)
.patchIssue(Authorization.get(ctx), repoOwner, repoName, issueIndex, issueData);
call.enqueue(new Callback<JsonElement>() {
@ -182,7 +188,7 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
if(response.code() == 201) {
if(tinyDb.getString("issueType").equalsIgnoreCase("Pull")) {
if(tinyDB.getString("issueType").equalsIgnoreCase("Pull")) {
Toasty.success(ctx, getString(R.string.editPrSuccessMessage));
}
@ -191,10 +197,9 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
Toasty.success(ctx, getString(R.string.editIssueSuccessMessage));
}
tinyDb.putBoolean("issueEdited", true);
tinyDb.putBoolean("resumeIssues", true);
tinyDB.putBoolean("issueEdited", true);
tinyDB.putBoolean("resumeIssues", true);
finish();
}
else if(response.code() == 401) {
@ -203,19 +208,17 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -236,20 +239,19 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
DatePickerDialog datePickerDialog = new DatePickerDialog(this,
(view, year, monthOfYear, dayOfMonth) -> editIssueDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth)), mYear, mMonth, mDay);
datePickerDialog.show();
}
else if(v == editIssueButton) {
processEditIssue();
}
}
private void getIssue(final String instanceUrl, final String instanceToken, final String loginUid, final String repoOwner, final String repoName, int issueIndex, int resultLimit) {
private void getIssue(final String instanceToken, final String loginUid, final String repoOwner, final String repoName, int issueIndex, int resultLimit) {
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex);
.getApiInterface(ctx)
.getIssueByIndex(Authorization.get(ctx), repoOwner, repoName, issueIndex);
call.enqueue(new Callback<Issues>() {
@ -272,9 +274,8 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
if(response.body().getId() > 0) {
Call<List<Milestones>> call_ = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getMilestones(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, 1, resultLimit, msState);
.getApiInterface(ctx)
.getMilestones(Authorization.get(ctx), repoOwner, repoName, 1, resultLimit, msState);
int checkMilestoneId = currentMilestoneId;
@ -319,9 +320,7 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
}, 500);
enableProcessButton();
}
}
@Override
@ -354,7 +353,6 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override

View File

@ -1,30 +1,28 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import org.gitnex.tea4j.models.FileDiffView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.FilesDiffAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityFileDiffBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.ParseDiff;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.FileDiffView;
import java.io.IOException;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -36,36 +34,28 @@ public class FileDiffActivity extends BaseActivity {
private TextView toolbarTitle;
private ListView mListView;
private ProgressBar mProgressBar;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_file_diff;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
Toolbar toolbar = findViewById(R.id.toolbar);
ActivityFileDiffBinding activityFileDiffBinding = ActivityFileDiffBinding.inflate(getLayoutInflater());
setContentView(activityFileDiffBinding.getRoot());
Toolbar toolbar = activityFileDiffBinding.toolbar;
setSupportActionBar(toolbar);
final TinyDB tinyDb = new TinyDB(appCtx);
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
toolbarTitle = findViewById(R.id.toolbar_title);
mListView = findViewById(R.id.listView);
mProgressBar = findViewById(R.id.progress_bar);
ImageView closeActivity = activityFileDiffBinding.close;
toolbarTitle = activityFileDiffBinding.toolbarTitle;
mListView = activityFileDiffBinding.listView;
mProgressBar = activityFileDiffBinding.progressBar;
mListView.setDivider(null);
@ -77,92 +67,70 @@ public class FileDiffActivity extends BaseActivity {
String pullIndex = tinyDb.getString("issueNumber");
boolean apiCall = true;
String instanceUrl = tinyDb.getString("instanceUrl");
// fallback for old gitea instances
if(new Version(tinyDb.getString("giteaVersion")).less("1.13.0")) {
apiCall = false;
instanceUrl = instanceUrl.substring(0, instanceUrl.lastIndexOf("api/v1/"));
}
getPullDiffContent(instanceUrl, repoOwner, repoName, pullIndex, instanceToken, apiCall);
boolean apiCall = !new Version(tinyDb.getString("giteaVersion")).less("1.13.0");
getPullDiffContent(repoOwner, repoName, pullIndex, apiCall);
}
private void getPullDiffContent(String instanceUrl, String owner, String repo, String pullIndex, String token, boolean apiCall) {
private void getPullDiffContent(String owner, String repo, String pullIndex, boolean apiCall) {
Call<ResponseBody> call;
if(apiCall) {
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getPullDiffContent(token, owner, repo, pullIndex);
}
else {
call = RetrofitClient.getInstance(instanceUrl, ctx).getWebInterface().getPullDiffContent(owner, repo, pullIndex);
}
Thread thread = new Thread(() -> {
call.enqueue(new Callback<ResponseBody>() {
Call<ResponseBody> call = apiCall ?
RetrofitClient.getApiInterface(ctx).getPullDiffContent(Authorization.get(ctx), owner, repo, pullIndex) :
RetrofitClient.getWebInterface(ctx).getPullDiffContent(Authorization.getWeb(ctx), owner, repo, pullIndex);
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
try {
if(response.code() == 200) {
Response<ResponseBody> response = call.execute();
assert response.body() != null;
try {
assert response.body() != null;
switch(response.code()) {
AppUtil appUtil = new AppUtil();
List<FileDiffView> fileContentsArray = ParseDiff.getFileDiffViewArray(response.body().string());
case 200:
List<FileDiffView> fileDiffViews = ParseDiff.getFileDiffViewArray(response.body().string());
int filesCount = fileContentsArray.size();
if(filesCount > 1) {
toolbarTitle.setText(getResources().getString(R.string.fileDiffViewHeader, Integer.toString(filesCount)));
}
else {
toolbarTitle.setText(getResources().getString(R.string.fileDiffViewHeaderSingle, Integer.toString(filesCount)));
}
int filesCount = fileDiffViews.size();
FilesDiffAdapter adapter = new FilesDiffAdapter(ctx, getSupportFragmentManager(), fileContentsArray);
mListView.setAdapter(adapter);
String toolbarTitleText = (filesCount > 1) ?
getResources().getString(R.string.fileDiffViewHeader, Integer.toString(filesCount)) :
getResources().getString(R.string.fileDiffViewHeaderSingle, Integer.toString(filesCount));
mProgressBar.setVisibility(View.GONE);
FilesDiffAdapter adapter = new FilesDiffAdapter(ctx, getSupportFragmentManager(), fileDiffViews);
}
catch(IOException e) {
e.printStackTrace();
}
runOnUiThread(() -> {
toolbarTitle.setText(toolbarTitleText);
mListView.setAdapter(adapter);
mProgressBar.setVisibility(View.GONE);
});
break;
case 401:
runOnUiThread(() -> AlertDialogs.authorizationTokenRevokedDialog(ctx,
getString(R.string.alertDialogTokenRevokedTitle),
getString(R.string.alertDialogTokenRevokedMessage),
getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getString(R.string.alertDialogTokenRevokedCopyPositiveButton)));
break;
case 403:
runOnUiThread(() -> Toasty.error(ctx, ctx.getString(R.string.authorizeError)));
break;
case 404:
runOnUiThread(() -> Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)));
break;
default:
runOnUiThread(() -> Toasty.error(ctx, getString(R.string.labelGeneralError)));
}
else if(response.code() == 401) {
} catch(IOException ignored) {}
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.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
thread.start();
}
private void initCloseListener() {
@ -171,8 +139,8 @@ public class FileDiffActivity extends BaseActivity {
getIntent().removeExtra("singleFileName");
finish();
};
}
}

View File

@ -1,68 +1,41 @@
package org.mian.gitnex.activities;
import android.app.Activity;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.text.Spanned;
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.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.util.FitPolicy;
import com.github.chrisbanes.photoview.PhotoView;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.core.app.NotificationCompat;
import com.vdurmont.emoji.EmojiParser;
import org.apache.commons.io.FileUtils;
import org.gitnex.tea4j.models.Files;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityFileViewBinding;
import org.mian.gitnex.fragments.BottomSheetFileViewerFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Images;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.highlightjs.HighlightJsView;
import org.mian.gitnex.helpers.highlightjs.models.Theme;
import org.mian.gitnex.models.Files;
import java.io.File;
import org.mian.gitnex.notifications.Notifications;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
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.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 java.util.Arrays;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -70,87 +43,35 @@ import retrofit2.Callback;
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 Context appCtx;
private ProgressBar mProgressBar;
private byte[] imageData;
private PDFView pdfView;
private LinearLayout pdfViewFrame;
private byte[] decodedPdf;
private Boolean pdfNightMode;
private String singleFileName;
private String fileSha;
private AppUtil appUtil;
private TinyDB tinyDb;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_file_view;
}
private ActivityFileViewBinding binding;
private Files file;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
appUtil = new AppUtil();
tinyDb = new TinyDB(appCtx);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
binding = ActivityFileViewBinding.inflate(getLayoutInflater());
String repoFullName = tinyDb.getString("repoFullName");
String repoBranch = tinyDb.getString("repoBranch");
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
tinyDB.putBoolean("enableMarkdownInFileView", false);
file = (Files) getIntent().getSerializableExtra("file");
binding.close.setOnClickListener(view -> finish());
binding.toolbarTitle.setMovementMethod(new ScrollingMovementMethod());
binding.toolbarTitle.setText(file.getPath());
String repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch");
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");
String repoOwner = parts[0];
String repoName = parts[1];
tinyDb.putBoolean("enableMarkdownInFileView", false);
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);
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) {
Log.i("singleFileName", singleFileName);
}
toolbar_title.setText(singleFileName);
getSingleFileContents(instanceUrl, instanceToken, repoOwner, repoName, singleFileName, repoBranch);
getSingleFileContents(repoOwner, repoName, file.getPath(), repoBranch);
}
@ -159,161 +80,143 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
super.onResume();
String repoFullName = tinyDb.getString("repoFullName");
String repoBranch = tinyDb.getString("repoBranch");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
String instanceUrl = tinyDb.getString("instanceUrl");
String loginUid = tinyDb.getString("loginUid");
String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDB.getBoolean("fileModified")) {
String repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
if(tinyDb.getBoolean("fileModified")) {
getSingleFileContents(instanceUrl, instanceToken, repoOwner, repoName, singleFileName, repoBranch);
tinyDb.putBoolean("fileModified", false);
getSingleFileContents(repoOwner, repoName, file.getPath(), repoBranch);
tinyDB.putBoolean("fileModified", false);
}
}
private void getSingleFileContents(final String owner, String repo, final String filename, String ref) {
private void getSingleFileContents(String instanceUrl, String token, final String owner, String repo, final String filename, String ref) {
Thread thread = new Thread(() -> {
Call<Files> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getSingleFileContents(token, owner, repo, filename, ref);
Call<ResponseBody> call = RetrofitClient
.getWebInterface(ctx)
.getFileContents(Authorization.getWeb(ctx), owner, repo, ref, filename);
call.enqueue(new Callback<Files>() {
try {
@Override
public void onResponse(@NonNull Call<Files> call, @NonNull retrofit2.Response<Files> response) {
Response<ResponseBody> response = call.execute();
if(response.code() == 200) {
assert response.body() != null;
ResponseBody responseBody = response.body();
if(!response.body().getContent().equals("")) {
if(responseBody != null) {
runOnUiThread(() -> binding.progressBar.setVisibility(View.GONE));
String fileExtension = FileUtils.getExtension(filename);
mProgressBar.setVisibility(View.GONE);
fileSha = response.body().getSha();
boolean processable = false;
// download file meta
tinyDb.putString("downloadFileName", filename);
tinyDb.putString("downloadFileContents", response.body().getContent());
switch(AppUtil.getFileType(fileExtension)) {
if(appUtil.imageExtension(fileExtension)) { // file is image
case IMAGE:
singleFileContentsFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
// See https://developer.android.com/guide/topics/media/media-formats#core
if(Arrays.asList("bmp", "gif", "jpg", "jpeg", "png", "webp", "heic", "heif").contains(fileExtension.toLowerCase())) {
imageData = Base64.decode(response.body().getContent(), Base64.DEFAULT);
Drawable imageDrawable = new BitmapDrawable(getResources(), BitmapFactory.decodeByteArray(imageData, 0, imageData.length));
imageView.setImageDrawable(imageDrawable);
processable = true;
byte[] pictureBytes = responseBody.bytes();
runOnUiThread(() -> {
binding.contents.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.GONE);
binding.photoView.setVisibility(View.VISIBLE);
binding.photoView.setImageBitmap(Images.scaleImage(pictureBytes, 1920));
});
}
break;
case UNKNOWN:
case TEXT:
if(file.getSize() > Constants.maximumFileViewerSize) {
break;
}
processable = true;
String text = responseBody.string();
runOnUiThread(() -> {
binding.photoView.setVisibility(View.GONE);
binding.contents.setContent(text, fileExtension);
if(tinyDB.getBoolean("enableMarkdownInFileView")) {
Markdown.render(ctx, EmojiParser.parseToUnicode(text), binding.markdown);
binding.contents.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.VISIBLE);
} else {
binding.markdownFrame.setVisibility(View.GONE);
binding.contents.setVisibility(View.VISIBLE);
}
});
break;
}
else if(appUtil.sourceCodeExtension(fileExtension)) { // file is sourcecode
imageView.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.VISIBLE);
if(!processable) { // While the file could still be non-binary,
// it's better we don't show it (to prevent any crashes and/or unwanted behavior) and let the user download it instead.
responseBody.close();
switch(tinyDb.getInt("fileviewerSourceCodeThemeId")) {
case 1:
singleCodeContents.setTheme(Theme.ARDUINO_LIGHT);
break;
case 2:
singleCodeContents.setTheme(Theme.GITHUB);
break;
case 3:
singleCodeContents.setTheme(Theme.FAR);
break;
case 4:
singleCodeContents.setTheme(Theme.IR_BLACK);
break;
case 5:
singleCodeContents.setTheme(Theme.ANDROID_STUDIO);
break;
default:
singleCodeContents.setTheme(Theme.MONOKAI_SUBLIME);
}
singleCodeContents.setSource(appUtil.decodeBase64(response.body().getContent()));
runOnUiThread(() -> {
binding.photoView.setVisibility(View.GONE);
binding.contents.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.VISIBLE);
binding.markdown.setText(getString(R.string.excludeFilesInFileViewer));
binding.markdown.setGravity(Gravity.CENTER);
binding.markdown.setTypeface(null, Typeface.BOLD);
});
}
else if(appUtil.pdfExtension(fileExtension)) { // file is pdf
} else {
imageView.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.VISIBLE);
runOnUiThread(() -> {
binding.markdown.setText("");
binding.progressBar.setVisibility(View.GONE);
});
}
} else {
pdfNightMode = tinyDb.getBoolean("enablePdfMode");
switch(response.code()) {
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();
case 401:
runOnUiThread(() -> AlertDialogs.authorizationTokenRevokedDialog(ctx,
getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)));
break;
}
else if(appUtil.excludeFilesInFileViewerExtension(fileExtension)) { // files need to be excluded
case 403:
runOnUiThread(() -> Toasty.error(ctx, ctx.getString(R.string.authorizeError)));
break;
imageView.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
case 404:
runOnUiThread(() -> Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)));
break;
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()));
}
default:
runOnUiThread(() -> Toasty.error(ctx, getString(R.string.labelGeneralError)));
}
else {
singleFileContents.setText("");
mProgressBar.setVisibility(View.GONE);
}
}
else if(response.code() == 401) {
} catch(IOException ignored) {}
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.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<Files> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
thread.start();
}
@Override
@ -323,9 +226,11 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
inflater.inflate(R.menu.files_view_menu, menu);
String fileExtension = FileUtils.getExtension(singleFileName);
if(!fileExtension.equalsIgnoreCase("md")) {
menu.getItem(0).setVisible(false);
if(!FileUtils.getExtension(file.getName())
.equalsIgnoreCase("md")) {
menu.getItem(0)
.setVisible(false);
}
return true;
@ -336,201 +241,158 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
int id = item.getItemId();
switch(id) {
case android.R.id.home:
if(id == android.R.id.home) {
finish();
return true;
case R.id.genericMenu:
finish();
return true;
BottomSheetFileViewerFragment bottomSheet = new BottomSheetFileViewerFragment();
bottomSheet.show(getSupportFragmentManager(), "fileViewerBottomSheet");
return true;
case R.id.markdown:
} else if(id == R.id.genericMenu) {
final Markwon markwon = Markwon.builder(Objects.requireNonNull(ctx)).usePlugin(CorePlugin.create())
.usePlugin(ImagesPlugin.create(plugin -> {
plugin.addSchemeHandler(new SchemeHandler() {
BottomSheetFileViewerFragment bottomSheet = new BottomSheetFileViewerFragment();
bottomSheet.show(getSupportFragmentManager(), "fileViewerBottomSheet");
return true;
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
} else if(id == R.id.markdown) {
final int resourceId = ctx.getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
ctx.getPackageName());
if(!tinyDB.getBoolean("enableMarkdownInFileView")) {
Markdown.render(ctx, EmojiParser.parseToUnicode(binding.contents.getContent()), binding.markdown);
final Drawable drawable = ctx.getDrawable(resourceId);
binding.contents.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.VISIBLE);
assert drawable != null;
return ImageItem.withResult(drawable);
}
tinyDB.putBoolean("enableMarkdownInFileView", true);
} else {
binding.markdownFrame.setVisibility(View.GONE);
binding.contents.setVisibility(View.VISIBLE);
@NonNull
@Override
public Collection<String> supportedSchemes() {
tinyDB.putBoolean("enableMarkdownInFileView", false);
}
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(drawable -> null);
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(ctx.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(ctx.getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
return true;
builder.codeTextColor(tinyDb.getInt("codeBlockColor")).codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(ctx))
.usePlugin(TaskListPlugin.create(ctx))
.usePlugin(HtmlPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
if(!tinyDb.getBoolean("enableMarkdownInFileView")) {
singleCodeContents.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setVisibility(View.VISIBLE);
Spanned bodyWithMD = markwon.toMarkdown(appUtil.decodeBase64(tinyDb.getString("downloadFileContents")));
markwon.setParsedMarkdown(singleFileContents, bodyWithMD);
tinyDb.putBoolean("enableMarkdownInFileView", true);
}
else {
singleCodeContents.setVisibility(View.VISIBLE);
singleFileContentsFrame.setVisibility(View.GONE);
singleFileContents.setVisibility(View.GONE);
singleCodeContents.setSource(appUtil.decodeBase64(tinyDb.getString("downloadFileContents")));
tinyDb.putBoolean("enableMarkdownInFileView", false);
}
return true;
default:
return super.onOptionsItemSelected(item);
} else {
return super.onOptionsItemSelected(item);
}
}
@Override
public void onButtonClicked(String text) {
if("downloadFile".equals(text)) {
requestFileDownload();
}
if("deleteFile".equals(text)) {
String fileExtension = FileUtils.getExtension(singleFileName);
String data = appUtil.decodeBase64(tinyDb.getString("downloadFileContents"));
Intent intent = new Intent(ctx, CreateFileActivity.class);
intent.putExtra("fileAction", 1);
intent.putExtra("filePath", singleFileName);
intent.putExtra("fileSha", fileSha);
if(!appUtil.imageExtension(fileExtension)) {
intent.putExtra("fileContents", data);
}
else {
intent.putExtra("fileContents", "");
}
intent.putExtra("fileAction", CreateFileActivity.FILE_ACTION_DELETE);
intent.putExtra("filePath", file.getPath());
intent.putExtra("fileSha", file.getSha());
ctx.startActivity(intent);
}
if("editFile".equals(text)) {
String fileExtension = FileUtils.getExtension(singleFileName);
String data = appUtil.decodeBase64(tinyDb.getString("downloadFileContents"));
Intent intent = new Intent(ctx, CreateFileActivity.class);
intent.putExtra("fileAction", 2);
intent.putExtra("filePath", singleFileName);
intent.putExtra("fileSha", fileSha);
if(!appUtil.imageExtension(fileExtension)) {
intent.putExtra("fileContents", data);
}
else {
intent.putExtra("fileContents", "");
}
if(binding.contents.getContent() != null &&
!binding.contents.getContent().isEmpty()) {
ctx.startActivity(intent);
Intent intent = new Intent(ctx, CreateFileActivity.class);
intent.putExtra("fileAction", CreateFileActivity.FILE_ACTION_EDIT);
intent.putExtra("filePath", file.getPath());
intent.putExtra("fileSha", file.getSha());
intent.putExtra("fileContents", binding.contents.getContent());
ctx.startActivity(intent);
} else {
Toasty.error(ctx, getString(R.string.fileTypeCannotBeEdited));
}
}
}
private void requestFileDownload() {
if(!tinyDb.getString("downloadFileContents").isEmpty()) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
int CREATE_REQUEST_CODE = 40;
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_TITLE, file.getName());
intent.setType("*/*");
File outputFileName = new File(tinyDb.getString("downloadFileName"));
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_TITLE, outputFileName.getName());
startActivityForResult(intent, CREATE_REQUEST_CODE);
}
else {
Toasty.warning(ctx, getString(R.string.waitLoadingDownloadFile));
}
activityResultLauncher.launch(intent);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
super.onActivityResult(requestCode, resultCode, data);
if (result.getResultCode() == Activity.RESULT_OK) {
if(requestCode == 40 && resultCode == RESULT_OK) {
assert result.getData() != null;
try {
assert data != null;
Uri uri = data.getData();
OutputStream outputStream = getContentResolver().openOutputStream(result.getData().getData());
assert uri != null;
OutputStream outputStream = getContentResolver().openOutputStream(uri);
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx, ctx.getPackageName())
.setContentTitle(getString(R.string.fileViewerNotificationTitleStarted))
.setContentText(getString(R.string.fileViewerNotificationDescriptionStarted, file.getName()))
.setSmallIcon(R.drawable.gitnex_transparent)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setChannelId(Constants.downloadNotificationChannelId)
.setProgress(100, 0, false)
.setOngoing(true);
byte[] dataAsBytes = Base64.decode(tinyDb.getString("downloadFileContents"), 0);
int notificationId = Notifications.uniqueNotificationId(ctx);
assert outputStream != null;
outputStream.write(dataAsBytes);
outputStream.close();
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);;
notificationManager.notify(notificationId, builder.build());
Toasty.success(ctx, getString(R.string.downloadFileSaved));
String repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
}
catch(IOException e) {
Thread thread = new Thread(() -> {
Log.e("errorFileDownloading", Objects.requireNonNull(e.getMessage()));
}
try {
Call<ResponseBody> call = RetrofitClient
.getWebInterface(ctx)
.getFileContents(Authorization.getWeb(ctx), repoOwner, repoName, repoBranch, file.getPath());
Response<ResponseBody> response = call.execute();
assert response.body() != null;
AppUtil.copyProgress(response.body().byteStream(), outputStream, file.getSize(), progress -> {
builder.setProgress(100, progress, false);
notificationManager.notify(notificationId, builder.build());
});
builder.setContentTitle(getString(R.string.fileViewerNotificationTitleFinished))
.setContentText(getString(R.string.fileViewerNotificationDescriptionFinished, file.getName()));
} catch(IOException ignored) {
builder.setContentTitle(getString(R.string.fileViewerNotificationTitleFailed))
.setContentText(getString(R.string.fileViewerNotificationDescriptionFailed, file.getName()));
} finally {
builder.setProgress(0,0,false)
.setOngoing(false);
notificationManager.notify(notificationId, builder.build());
}
});
thread.start();
} catch(IOException ignored) {}
}
}
private void initCloseListener() {
onClickListener = view -> {
getIntent().removeExtra("singleFileName");
finish();
};
}
});
}

View File

@ -6,14 +6,10 @@ import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.Html;
import android.text.Spanned;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@ -26,12 +22,19 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.text.HtmlCompat;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.amulyakhare.textdrawable.TextDrawable;
import com.google.gson.JsonElement;
import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.Collaborators;
import org.gitnex.tea4j.models.Issues;
import org.gitnex.tea4j.models.Labels;
import org.gitnex.tea4j.models.UpdateIssueAssignees;
import org.gitnex.tea4j.models.WatchInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.AssigneesActions;
import org.mian.gitnex.actions.LabelsActions;
@ -51,42 +54,22 @@ import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.helpers.LabelWidthCalculator;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UserMentions;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.UpdateIssueAssignees;
import org.mian.gitnex.models.WatchInfo;
import org.mian.gitnex.viewmodels.IssueCommentsViewModel;
import org.mian.gitnex.views.ReactionList;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
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.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;
@ -98,13 +81,7 @@ import retrofit2.Response;
public class IssueDetailActivity extends BaseActivity implements LabelsListAdapter.LabelsListAdapterListener, AssigneesListAdapter.AssigneesListAdapterListener, BottomSheetSingleIssueFragment.BottomSheetListener {
private IssueCommentsAdapter adapter;
final Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
private String instanceUrl;
private String loginUid;
private String instanceToken;
private String repoOwner;
private String repoName;
private int issueIndex;
@ -114,8 +91,8 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
private List<Integer> currentLabelsIds = new ArrayList<>();
private List<Integer> labelsIds = new ArrayList<>();
private List<Labels> labelsList = new ArrayList<>();
private List<Collaborators> assigneesList = new ArrayList<>();
private final List<Labels> labelsList = new ArrayList<>();
private final List<Collaborators> assigneesList = new ArrayList<>();
private List<String> assigneesListData = new ArrayList<>();
private List<String> currentAssignees = new ArrayList<>();
@ -126,31 +103,19 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
private CustomAssigneesSelectionDialogBinding assigneesBinding;
private ActivityIssueDetailBinding viewBinding;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_issue_detail;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
viewBinding = ActivityIssueDetailBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
setContentView(viewBinding.getRoot());
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repoOwner = parts[0];
repoName = parts[1];
issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
issueIndex = Integer.parseInt(tinyDB.getString("issueNumber"));
setSupportActionBar(viewBinding.toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repoName);
@ -163,12 +128,18 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(viewBinding.recyclerView.getContext(), DividerItemDecoration.VERTICAL);
viewBinding.recyclerView.addItemDecoration(dividerItemDecoration);
viewBinding.addNewComment.setOnClickListener(v -> BottomSheetReplyFragment.newInstance(new Bundle()).show(getSupportFragmentManager(), "replyBottomSheet"));
viewBinding.addNewComment.setOnClickListener(v -> {
BottomSheetReplyFragment bottomSheetReplyFragment = BottomSheetReplyFragment.newInstance(new Bundle());
bottomSheetReplyFragment.setOnInteractedListener(this::onResume);
bottomSheetReplyFragment.show(getSupportFragmentManager(), "replyBottomSheet");
});
labelsAdapter = new LabelsListAdapter(labelsList, IssueDetailActivity.this, currentLabelsIds);
assigneesAdapter = new AssigneesListAdapter(ctx, assigneesList, IssueDetailActivity.this, currentAssignees);
LabelsActions.getCurrentIssueLabels(ctx, instanceUrl, loginUid, instanceToken, repoOwner, repoName, issueIndex, currentLabelsIds);
AssigneesActions.getCurrentIssueAssignees(ctx, instanceUrl, loginUid, instanceToken, repoOwner, repoName, issueIndex, currentAssignees);
LabelsActions.getCurrentIssueLabels(ctx, repoOwner, repoName, issueIndex, currentLabelsIds);
AssigneesActions.getCurrentIssueAssignees(ctx, repoOwner, repoName, issueIndex, currentAssignees);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@ -197,14 +168,14 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.pullToRefresh.setRefreshing(false);
IssueCommentsViewModel
.loadIssueComments(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex,
.loadIssueComments(Authorization.get(ctx), repoOwner, repoName, issueIndex,
ctx);
}, 500));
Typeface myTypeface;
switch(tinyDb.getInt("customFontId", -1)) {
switch(tinyDB.getInt("customFontId", -1)) {
case 1:
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(ctx).getAssets(), "fonts/manroperegular.ttf");
@ -223,8 +194,12 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.toolbarTitle.setTypeface(myTypeface);
viewBinding.toolbarTitle.setText(repoName);
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
fetchDataAsync(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
getSingleIssue(repoOwner, repoName, issueIndex);
fetchDataAsync(repoOwner, repoName, issueIndex);
if(getIntent().getStringExtra("openPrDiff") != null && getIntent().getStringExtra("openPrDiff").equals("true")) {
startActivity(new Intent(ctx, FileDiffActivity.class));
}
}
@ -233,6 +208,10 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
switch(text) {
case "onResume":
onResume();
break;
case "showLabels":
showLabels();
break;
@ -293,7 +272,8 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
}
});
AssigneesActions.getRepositoryAssignees(ctx, instanceUrl, instanceToken, repoOwner, repoName, assigneesList, dialogAssignees, assigneesAdapter, assigneesBinding);
dialogAssignees.show();
AssigneesActions.getRepositoryAssignees(ctx, repoOwner, repoName, assigneesList, dialogAssignees, assigneesAdapter, assigneesBinding);
}
public void showLabels() {
@ -329,7 +309,8 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
}
});
LabelsActions.getRepositoryLabels(ctx, instanceUrl, instanceToken, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
dialogLabels.show();
LabelsActions.getRepositoryLabels(ctx, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
}
private void updateIssueAssignees() {
@ -339,9 +320,8 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
Call<JsonElement> call3;
call3 = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.patchIssueAssignees(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, updateAssigneeJson);
.getApiInterface(ctx)
.patchIssueAssignees(Authorization.get(ctx), repoOwner, repoName, issueIndex, updateAssigneeJson);
call3.enqueue(new Callback<JsonElement>() {
@ -356,9 +336,9 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.frameAssignees.removeAllViews();
viewBinding.frameLabels.removeAllViews();
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
getSingleIssue(repoOwner, repoName, issueIndex);
currentAssignees.clear();
new Handler(Looper.getMainLooper()).postDelayed(() -> AssigneesActions.getCurrentIssueAssignees(ctx, instanceUrl, loginUid, instanceToken, repoOwner, repoName, issueIndex, currentAssignees), 1000);
new Handler(Looper.getMainLooper()).postDelayed(() -> AssigneesActions.getCurrentIssueAssignees(ctx, repoOwner, repoName, issueIndex, currentAssignees), 1000);
}
else if(response2.code() == 401) {
@ -395,9 +375,8 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
Labels patchIssueLabels = new Labels(labelsIds);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.updateIssueLabels(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, patchIssueLabels);
.getApiInterface(ctx)
.updateIssueLabels(Authorization.get(ctx), repoOwner, repoName, issueIndex, patchIssueLabels);
call.enqueue(new Callback<JsonElement>() {
@ -411,9 +390,9 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.frameAssignees.removeAllViews();
viewBinding.frameLabels.removeAllViews();
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
getSingleIssue(repoOwner, repoName, issueIndex);
currentLabelsIds.clear();
new Handler(Looper.getMainLooper()).postDelayed(() -> LabelsActions.getCurrentIssueLabels(ctx, instanceUrl, loginUid, instanceToken, repoOwner, repoName, issueIndex, currentLabelsIds), 1000);
new Handler(Looper.getMainLooper()).postDelayed(() -> LabelsActions.getCurrentIssueLabels(ctx, repoOwner, repoName, issueIndex, currentLabelsIds), 1000);
}
else if(response.code() == 401) {
@ -458,18 +437,26 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
int id = item.getItemId();
switch(id) {
case android.R.id.home:
finish();
return true;
case R.id.genericMenu:
BottomSheetSingleIssueFragment bottomSheet = new BottomSheetSingleIssueFragment();
bottomSheet.show(getSupportFragmentManager(), "singleIssueBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
if(id == android.R.id.home) {
if(getIntent().getStringExtra("openedFromLink") != null && getIntent().getStringExtra("openedFromLink").equals("true")) {
Intent intent = new Intent(ctx, RepoDetailActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
finish();
return true;
}
else if(id == R.id.genericMenu) {
BottomSheetSingleIssueFragment bottomSheet = new BottomSheetSingleIssueFragment();
bottomSheet.show(getSupportFragmentManager(), "singleIssueBottomSheet");
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
@Override
@ -477,84 +464,87 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
super.onResume();
if(tinyDb.getBoolean("commentPosted")) {
if(tinyDB.getBoolean("commentPosted")) {
viewBinding.scrollViewComments.post(() -> {
IssueCommentsViewModel
.loadIssueComments(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex,
.loadIssueComments(Authorization.get(ctx), repoOwner, repoName, issueIndex,
ctx);
new Handler(Looper.getMainLooper()).postDelayed(() -> viewBinding.scrollViewComments.fullScroll(ScrollView.FOCUS_DOWN), 1000);
tinyDb.putBoolean("commentPosted", false);
tinyDB.putBoolean("commentPosted", false);
});
}
if(tinyDb.getBoolean("commentEdited")) {
if(tinyDB.getBoolean("commentEdited")) {
viewBinding.scrollViewComments.post(() -> {
IssueCommentsViewModel
.loadIssueComments(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex,
.loadIssueComments(Authorization.get(ctx), repoOwner, repoName, issueIndex,
ctx);
tinyDb.putBoolean("commentEdited", false);
tinyDB.putBoolean("commentEdited", false);
});
}
if(tinyDb.getBoolean("singleIssueUpdate")) {
if(tinyDB.getBoolean("singleIssueUpdate")) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
viewBinding.frameAssignees.removeAllViews();
viewBinding.frameLabels.removeAllViews();
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
tinyDb.putBoolean("singleIssueUpdate", false);
getSingleIssue(repoOwner, repoName, issueIndex);
tinyDB.putBoolean("singleIssueUpdate", false);
}, 500);
}
if(tinyDb.getBoolean("issueEdited")) {
if(tinyDB.getBoolean("issueEdited")) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
viewBinding.frameAssignees.removeAllViews();
viewBinding.frameLabels.removeAllViews();
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
tinyDb.putBoolean("issueEdited", false);
getSingleIssue(repoOwner, repoName, issueIndex);
tinyDB.putBoolean("issueEdited", false);
}, 500);
}
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner, String repo, int index, String loginUid) {
private void fetchDataAsync(String owner, String repo, int index) {
IssueCommentsViewModel issueCommentsModel = new ViewModelProvider(this).get(IssueCommentsViewModel.class);
issueCommentsModel.getIssueCommentList(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), owner, repo, index, ctx)
issueCommentsModel.getIssueCommentList(Authorization.get(ctx), owner, repo, index, ctx)
.observe(this, issueCommentsMain -> {
assert issueCommentsMain != null;
if(issueCommentsMain.size() > 0) {
viewBinding.divider.setVisibility(View.VISIBLE);
}
adapter = new IssueCommentsAdapter(ctx, getSupportFragmentManager(), issueCommentsMain);
Bundle bundle = new Bundle();
bundle.putString("repoOwner", repoOwner);
bundle.putString("repoName", repoName);
bundle.putInt("issueNumber", issueIndex);
adapter = new IssueCommentsAdapter(ctx, bundle, issueCommentsMain, getSupportFragmentManager(), this::onResume);
viewBinding.recyclerView.setAdapter(adapter);
});
}
private void getSingleIssue(String instanceUrl, String instanceToken, String repoOwner, String repoName, int issueIndex, String loginUid) {
private void getSingleIssue(String repoOwner, String repoName, int issueIndex) {
final TinyDB tinyDb = new TinyDB(appCtx);
Call<Issues> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex);
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
Call<Issues> call = RetrofitClient.getApiInterface(ctx)
.getIssueByIndex(Authorization.get(ctx), repoOwner, repoName, issueIndex);
call.enqueue(new Callback<Issues>() {
@ -567,6 +557,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
assert singleIssue != null;
viewBinding.issuePrState.setVisibility(View.VISIBLE);
if(singleIssue.getPull_request() != null) {
if(singleIssue.getPull_request().isMerged()) { // merged
@ -587,50 +578,8 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.issuePrState.setImageResource(R.drawable.ic_issue_closed_red);
}
final Markwon markwon = Markwon.builder(Objects.requireNonNull(ctx)).usePlugin(CorePlugin.create())
.usePlugin(ImagesPlugin.create(plugin -> {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = ctx.getResources()
.getIdentifier(raw.substring("drawable://".length()), "drawable", ctx.getPackageName());
final Drawable drawable = ctx.getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(drawable -> null);
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(ctx.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(ctx.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(getResources().getColor(R.color.lightBlue));
}
}).usePlugin(TablePlugin.create(ctx)).usePlugin(TaskListPlugin.create(ctx)).usePlugin(HtmlPlugin.create())
.usePlugin(StrikethroughPlugin.create()).usePlugin(LinkifyPlugin.create()).build();
TinyDB tinyDb = new TinyDB(appCtx);
final String locale = tinyDb.getString("locale");
TinyDB tinyDb = TinyDB.getInstance(appCtx);
final Locale locale = getResources().getConfiguration().locale;
final String timeFormat = tinyDb.getString("dateFormat");
tinyDb.putString("issueState", singleIssue.getState());
tinyDb.putString("issueTitle", singleIssue.getTitle());
@ -638,12 +587,23 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
PicassoService.getInstance(ctx).get().load(singleIssue.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(viewBinding.assigneeAvatar);
String issueNumber_ = "<font color='" + appCtx.getResources().getColor(R.color.lightGray) + "'>" + appCtx.getResources()
String issueNumber_ = "<font color='" + ResourcesCompat.getColor(getResources(), R.color.lightGray, null) + "'>" + appCtx.getResources()
.getString(R.string.hash) + singleIssue.getNumber() + "</font>";
viewBinding.issueTitle.setText(Html.fromHtml(issueNumber_ + " " + singleIssue.getTitle()));
viewBinding.issueTitle.setText(HtmlCompat.fromHtml(issueNumber_ + " " + EmojiParser.parseToUnicode(singleIssue.getTitle()), HtmlCompat.FROM_HTML_MODE_LEGACY));
String cleanIssueDescription = singleIssue.getBody().trim();
Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueDescription));
markwon.setParsedMarkdown(viewBinding.issueDescription, UserMentions.UserMentionsFunc(ctx, bodyWithMD, cleanIssueDescription));
viewBinding.assigneeAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(ctx, ProfileActivity.class);
intent.putExtra("username", singleIssue.getUser().getLogin());
ctx.startActivity(intent);
});
viewBinding.assigneeAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(ctx, singleIssue.getUser().getLogin(), ctx.getString(R.string.copyLoginIdToClipBoard, singleIssue.getUser().getLogin()));
return true;
});
Markdown.render(ctx, EmojiParser.parseToUnicode(cleanIssueDescription), viewBinding.issueDescription);
RelativeLayout.LayoutParams paramsDesc = (RelativeLayout.LayoutParams) viewBinding.issueDescription.getLayoutParams();
@ -651,7 +611,9 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
params1.setMargins(15, 0, 0, 0);
if(singleIssue.getAssignees() != null) {
viewBinding.assigneesScrollView.setVisibility(View.VISIBLE);
for(int i = 0; i < singleIssue.getAssignees().size(); i++) {
ImageView assigneesView = new ImageView(ctx);
@ -662,18 +624,33 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.frameAssignees.addView(assigneesView);
assigneesView.setLayoutParams(params1);
if(!singleIssue.getAssignees().get(i).getFull_name().equals("")) {
int finalI = i;
assigneesView.setOnClickListener(loginId -> {
Intent intent = new Intent(ctx, ProfileActivity.class);
intent.putExtra("username", singleIssue.getAssignees().get(finalI).getLogin());
ctx.startActivity(intent);
});
assigneesView.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(ctx, singleIssue.getAssignees().get(finalI).getLogin(), ctx.getString(R.string.copyLoginIdToClipBoard, singleIssue.getAssignees().get(finalI).getLogin()));
return true;
});
/*if(!singleIssue.getAssignees().get(i).getFull_name().equals("")) {
assigneesView.setOnClickListener(
new ClickListener(getString(R.string.assignedTo, singleIssue.getAssignees().get(i).getFull_name()), ctx));
}
else {
assigneesView.setOnClickListener(
new ClickListener(getString(R.string.assignedTo, singleIssue.getAssignees().get(i).getLogin()), ctx));
}
}*/
}
}
else {
viewBinding.assigneesScrollView.setVisibility(View.GONE);
}
@ -682,6 +659,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
params.setMargins(0, 0, 15, 0);
if(singleIssue.getLabels() != null) {
viewBinding.labelsScrollView.setVisibility(View.VISIBLE);
for(int i = 0; i < singleIssue.getLabels().size(); i++) {
@ -705,28 +683,29 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
labelsView.setImageDrawable(drawable);
viewBinding.frameLabels.addView(labelsView);
}
}
else {
viewBinding.labelsScrollView.setVisibility(View.GONE);
}
if(singleIssue.getDue_date() != null) {
if(timeFormat.equals("normal") || timeFormat.equals("pretty")) {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", new Locale(locale));
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", locale);
String dueDate = formatter.format(singleIssue.getDue_date());
viewBinding.issueDueDate.setText(dueDate);
viewBinding.issueDueDate
.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(singleIssue.getDue_date()), ctx));
}
else if(timeFormat.equals("normal1")) {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", new Locale(locale));
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", locale);
String dueDate = formatter.format(singleIssue.getDue_date());
viewBinding.issueDueDate.setText(dueDate);
}
}
else {
@ -736,6 +715,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
String edited;
if(!singleIssue.getUpdated_at().equals(singleIssue.getCreated_at())) {
edited = getString(R.string.colorfulBulletSpan) + getString(R.string.modifiedText);
viewBinding.issueModified.setVisibility(View.VISIBLE);
viewBinding.issueModified.setText(edited);
@ -743,53 +723,79 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(singleIssue.getUpdated_at()), ctx));
}
else {
viewBinding.issueModified.setVisibility(View.INVISIBLE);
}
if((singleIssue.getDue_date() == null && singleIssue.getMilestone() == null) && singleIssue.getAssignees() != null) {
paramsDesc.setMargins(0, 35, 0, 0);
viewBinding.issueDescription.setLayoutParams(paramsDesc);
}
else if(singleIssue.getDue_date() == null && singleIssue.getMilestone() == null) {
paramsDesc.setMargins(0, 55, 0, 0);
viewBinding.issueDescription.setLayoutParams(paramsDesc);
}
else if(singleIssue.getAssignees() == null) {
paramsDesc.setMargins(0, 35, 0, 0);
viewBinding.issueDescription.setLayoutParams(paramsDesc);
}
else {
paramsDesc.setMargins(0, 15, 0, 0);
viewBinding.issueDescription.setLayoutParams(paramsDesc);
}
viewBinding.issueCreatedTime.setText(TimeHelper.formatTime(singleIssue.getCreated_at(), new Locale(locale), timeFormat, ctx));
viewBinding.issueCreatedTime.setText(TimeHelper.formatTime(singleIssue.getCreated_at(), locale, timeFormat, ctx));
viewBinding.issueCreatedTime.setVisibility(View.VISIBLE);
if(timeFormat.equals("pretty")) {
viewBinding.issueCreatedTime
.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(singleIssue.getCreated_at()), ctx));
}
Bundle bundle = new Bundle();
bundle.putString("repoOwner", repoOwner);
bundle.putString("repoName", repoName);
bundle.putInt("issueId", singleIssue.getNumber());
ReactionList reactionList = new ReactionList(ctx, bundle);
viewBinding.commentReactionBadges.removeAllViews();
viewBinding.commentReactionBadges.addView(reactionList);
reactionList.setOnReactionAddedListener(() -> {
if(viewBinding.commentReactionBadges.getVisibility() != View.VISIBLE) {
viewBinding.commentReactionBadges.post(() -> viewBinding.commentReactionBadges.setVisibility(View.VISIBLE));
}
});
if(singleIssue.getMilestone() != null) {
viewBinding.issueMilestone.setVisibility(View.VISIBLE);
viewBinding.issueMilestone.setText(getString(R.string.issueMilestone, singleIssue.getMilestone().getTitle()));
}
else {
viewBinding.issueMilestone.setVisibility(View.GONE);
}
if(!singleIssue.getUser().getFull_name().equals("")) {
/*if(!singleIssue.getUser().getFull_name().equals("")) {
viewBinding.assigneeAvatar.setOnClickListener(
new ClickListener(ctx.getResources().getString(R.string.issueCreator) + singleIssue.getUser().getFull_name(), ctx));
}
else {
viewBinding.assigneeAvatar.setOnClickListener(
new ClickListener(ctx.getResources().getString(R.string.issueCreator) + singleIssue.getUser().getLogin(), ctx));
}
}*/
viewBinding.progressBar.setVisibility(View.GONE);
}
else if(response.code() == 401) {
@ -813,9 +819,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
Intent mainIntent = new Intent(ctx, MainActivity.class);
ctx.startActivity(mainIntent);
finish();
}
}
@Override
@ -828,8 +832,8 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
Call<WatchInfo> call2 = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface()
.checkIssueWatchStatus(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex);
Call<WatchInfo> call2 = RetrofitClient.getApiInterface(appCtx)
.checkIssueWatchStatus(Authorization.get(ctx), repoOwner, repoName, issueIndex);
call2.enqueue(new Callback<WatchInfo>() {
@ -840,21 +844,17 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
assert response.body() != null;
tinyDb.putBoolean("issueSubscribed", response.body().getSubscribed());
}
else {
tinyDb.putBoolean("issueSubscribed", false);
}
}
@Override
public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) {
tinyDb.putBoolean("issueSubscribed", false);
}
});

View File

@ -1,8 +1,8 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
@ -10,23 +10,24 @@ import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import org.gitnex.tea4j.models.GiteaVersion;
import org.gitnex.tea4j.models.UserInfo;
import org.gitnex.tea4j.models.UserTokens;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.databinding.ActivityLoginBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.NetworkObserver;
import org.mian.gitnex.helpers.NetworkStatusObserver;
import org.mian.gitnex.helpers.PathsHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.models.UserTokens;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.List;
@ -46,10 +47,6 @@ public class LoginActivity extends BaseActivity {
private enum LoginType {BASIC, TOKEN}
private Context appCtx;
private Context ctx = this;
private TinyDB tinyDB;
private Button loginButton;
private EditText instanceUrlET, loginUidET, loginPassword, otpCode, loginTokenCode;
private AutoCompleteTextView protocolSpinner;
@ -57,41 +54,39 @@ public class LoginActivity extends BaseActivity {
private String device_id = "token";
private String selectedProtocol;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_login;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDB = new TinyDB(appCtx);
NetworkObserver networkMonitor = new NetworkObserver(ctx);
ActivityLoginBinding activityLoginBinding = ActivityLoginBinding.inflate(getLayoutInflater());
setContentView(activityLoginBinding.getRoot());
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);
protocolSpinner = findViewById(R.id.httpsSpinner);
loginMethod = findViewById(R.id.loginMethod);
loginTokenCode = findViewById(R.id.loginTokenCode);
NetworkStatusObserver networkStatusObserver = NetworkStatusObserver.getInstance(ctx);
((TextView) findViewById(R.id.appVersion)).setText(AppUtil.getAppVersion(appCtx));
loginButton = activityLoginBinding.loginButton;
instanceUrlET = activityLoginBinding.instanceUrl;
loginUidET = activityLoginBinding.loginUid;
loginPassword = activityLoginBinding.loginPasswd;
otpCode = activityLoginBinding.otpCode;
protocolSpinner = activityLoginBinding.httpsSpinner;
loginMethod = activityLoginBinding.loginMethod;
loginTokenCode = activityLoginBinding.loginTokenCode;
activityLoginBinding.appVersion.setText(AppUtil.getAppVersion(appCtx));
ArrayAdapter<Protocol> adapterProtocols = new ArrayAdapter<>(LoginActivity.this, R.layout.list_spinner_items, Protocol.values());
protocolSpinner.setAdapter(adapterProtocols);
instanceUrlET.setText(getIntent().getStringExtra("instanceUrl"));
protocolSpinner.setAdapter(adapterProtocols);
protocolSpinner.setSelection(0);
protocolSpinner.setOnItemClickListener((parent, view, position, id) -> {
selectedProtocol = String.valueOf(parent.getItemAtPosition(position));
if(selectedProtocol.equals(String.valueOf(Protocol.HTTP))) {
Toasty.warning(ctx, getResources().getString(R.string.protocolError));
}
});
@ -121,18 +116,24 @@ public class LoginActivity extends BaseActivity {
}
});
networkMonitor.onInternetStateListener(isAvailable -> {
Handler handler = new Handler(getMainLooper());
if(isAvailable) {
networkStatusObserver.registerNetworkStatusListener(hasNetworkConnection -> {
enableProcessButton();
}
else {
handler.post(() -> {
disableProcessButton();
loginButton.setText(getResources().getString(R.string.btnLogin));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
}
if(hasNetworkConnection) {
enableProcessButton();
}
else {
disableProcessButton();
loginButton.setText(getResources().getString(R.string.btnLogin));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
}
});
});
loadDefaults();
@ -141,9 +142,7 @@ public class LoginActivity extends BaseActivity {
disableProcessButton();
login();
});
}
private void login() {
@ -211,7 +210,7 @@ public class LoginActivity extends BaseActivity {
int loginOTP = (otpCode.length() > 0) ? Integer.parseInt(otpCode.getText().toString().trim()) : 0;
tinyDB.putString("loginUid", loginUid);
versionCheck(instanceUrl.toString(), loginUid, loginPass, loginOTP, loginToken, loginType);
versionCheck(loginUid, loginPass, loginOTP, loginToken, loginType);
}
else {
@ -221,11 +220,9 @@ public class LoginActivity extends BaseActivity {
Toasty.error(ctx, getResources().getString(R.string.loginTokenError));
enableProcessButton();
return;
}
versionCheck(instanceUrl.toString(), loginUid, loginPass, 123, loginToken, loginType);
versionCheck(loginUid, loginPass, 123, loginToken, loginType);
}
}
@ -234,27 +231,25 @@ public class LoginActivity extends BaseActivity {
Log.e("onFailure-login", e.toString());
Toasty.error(ctx, getResources().getString(R.string.malformedUrl));
enableProcessButton();
}
}
private void versionCheck(final String instanceUrl, final String loginUid, final String loginPass, final int loginOTP, final String loginToken,
private void versionCheck(final String loginUid, final String loginPass, final int loginOTP, final String loginToken,
final LoginType loginType) {
Call<GiteaVersion> callVersion;
if(!loginToken.equals("")) {
callVersion = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getGiteaVersionWithToken("token " + loginToken);
callVersion = RetrofitClient.getApiInterface(appCtx).getGiteaVersionWithToken("token " + loginToken);
}
else {
String credential = Credentials.basic(loginUid, loginPass, StandardCharsets.UTF_8);
callVersion =
(loginOTP != 0) ? RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getGiteaVersionWithOTP(credential, loginOTP) :
RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getGiteaVersionWithBasic(credential);
(loginOTP != 0) ? RetrofitClient.getApiInterface(appCtx).getGiteaVersionWithOTP(credential, loginOTP) :
RetrofitClient.getApiInterface(appCtx).getGiteaVersionWithBasic(credential);
}
callVersion.enqueue(new Callback<GiteaVersion>() {
@ -265,9 +260,10 @@ public class LoginActivity extends BaseActivity {
if(responseVersion.code() == 200) {
GiteaVersion version = responseVersion.body();
assert version != null;
if(!Version.valid(version.getVersion())) {
Toasty.error(ctx, getResources().getString(R.string.versionUnknown));
enableProcessButton();
return;
@ -278,11 +274,13 @@ public class LoginActivity extends BaseActivity {
if(gitea_version.less(getString(R.string.versionLow))) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(ctx).setTitle(getString(R.string.versionAlertDialogHeader))
.setMessage(getResources().getString(R.string.versionUnsupportedOld, version.getVersion())).setIcon(R.drawable.ic_warning)
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(ctx)
.setTitle(getString(R.string.versionAlertDialogHeader))
.setMessage(getResources().getString(R.string.versionUnsupportedOld, version.getVersion()))
.setIcon(R.drawable.ic_warning)
.setCancelable(true);
alertDialogBuilder.setNegativeButton(getString(R.string.cancelButton), (dialog, which) -> {
alertDialogBuilder.setNeutralButton(getString(R.string.cancelButton), (dialog, which) -> {
dialog.dismiss();
enableProcessButton();
@ -291,7 +289,7 @@ public class LoginActivity extends BaseActivity {
alertDialogBuilder.setPositiveButton(getString(R.string.textContinue), (dialog, which) -> {
dialog.dismiss();
login(loginType, instanceUrl, loginUid, loginPass, loginOTP, loginToken);
login(loginType, loginUid, loginPass, loginOTP, loginToken);
});
alertDialogBuilder.create().show();
@ -299,32 +297,34 @@ public class LoginActivity extends BaseActivity {
}
else if(gitea_version.lessOrEqual(getString(R.string.versionHigh))) {
login(loginType, instanceUrl, loginUid, loginPass, loginOTP, loginToken);
login(loginType, loginUid, loginPass, loginOTP, loginToken);
}
else {
Toasty.warning(ctx, getResources().getString(R.string.versionUnsupportedNew));
login(loginType, instanceUrl, loginUid, loginPass, loginOTP, loginToken);
login(loginType, loginUid, loginPass, loginOTP, loginToken);
}
}
else if(responseVersion.code() == 403) {
login(loginType, instanceUrl, loginUid, loginPass, loginOTP, loginToken);
login(loginType, loginUid, loginPass, loginOTP, loginToken);
}
}
private void login(LoginType loginType, String instanceUrl, String loginUid, String loginPass, int loginOTP, String loginToken) {
private void login(LoginType loginType, String loginUid, String loginPass, int loginOTP, String loginToken) {
// ToDo: before store/create token: get UserInfo to check DB/AccountManager if there already exist a token
// the setup methods then can better handle all different cases
if(loginType == LoginType.BASIC) {
setup(instanceUrl, loginUid, loginPass, loginOTP);
setup(loginUid, loginPass, loginOTP);
}
else if(loginType == LoginType.TOKEN) { // Token
setupUsingExistingToken(instanceUrl, loginToken);
setupUsingExistingToken(loginToken);
}
}
@ -338,9 +338,9 @@ public class LoginActivity extends BaseActivity {
});
}
private void setupUsingExistingToken(String instanceUrl, final String loginToken) {
private void setupUsingExistingToken(final String loginToken) {
Call<UserInfo> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserInfo("token " + loginToken);
Call<UserInfo> call = RetrofitClient.getApiInterface(appCtx).getUserInfo("token " + loginToken);
call.enqueue(new Callback<UserInfo>() {
@ -352,6 +352,7 @@ public class LoginActivity extends BaseActivity {
switch(response.code()) {
case 200:
assert userDetails != null;
tinyDB.putBoolean("loggedInMode", true);
tinyDB.putString(userDetails.getLogin() + "-token", loginToken);
@ -359,20 +360,20 @@ public class LoginActivity extends BaseActivity {
tinyDB.putString("userLogin", userDetails.getUsername());
// insert new account to db if does not exist
String accountName = userDetails.getUsername() + "@" + instanceUrl;
UserAccountsApi userAccountsApi = new UserAccountsApi(ctx);
int checkAccount = userAccountsApi.getCount(accountName);
String accountName = userDetails.getUsername() + "@" + TinyDB.getInstance(ctx).getString("instanceUrl");
UserAccountsApi userAccountsApi = BaseApi.getInstance(ctx, UserAccountsApi.class);
boolean userAccountExists = userAccountsApi.userAccountExists(accountName);
long accountId;
if(checkAccount == 0) {
if(!userAccountExists) {
accountId = userAccountsApi.insertNewAccount(accountName, instanceUrl, userDetails.getUsername(), loginToken, "");
accountId = userAccountsApi.createNewAccount(accountName, TinyDB.getInstance(ctx).getString("instanceUrl"), userDetails.getUsername(), loginToken, "");
tinyDB.putInt("currentActiveAccountId", (int) accountId);
}
else {
userAccountsApi.updateTokenByAccountName(accountName, loginToken);
UserAccount data = userAccountsApi.getAccountData(accountName);
UserAccount data = userAccountsApi.getAccountByName(accountName);
tinyDB.putInt("currentActiveAccountId", data.getAccountId());
}
@ -380,18 +381,16 @@ public class LoginActivity extends BaseActivity {
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
break;
case 401:
Toasty.error(ctx, getResources().getString(R.string.unauthorizedApiError));
enableProcessButton();
break;
default:
Toasty.error(ctx, getResources().getString(R.string.genericApiStatusError) + response.code());
enableProcessButton();
}
}
@Override
@ -400,13 +399,12 @@ public class LoginActivity extends BaseActivity {
Log.e("onFailure", t.toString());
Toasty.error(ctx, getResources().getString(R.string.genericError));
enableProcessButton();
}
});
}
private void setup(final String instanceUrl, final String loginUid, final String loginPass, final int loginOTP) {
private void setup(final String loginUid, final String loginPass, final int loginOTP) {
final String credential = Credentials.basic(loginUid, loginPass, StandardCharsets.UTF_8);
final String tokenName = "gitnex-app-" + device_id;
@ -414,11 +412,11 @@ public class LoginActivity extends BaseActivity {
Call<List<UserTokens>> call;
if(loginOTP != 0) {
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserTokensWithOTP(credential, loginOTP, loginUid);
call = RetrofitClient.getApiInterface(appCtx).getUserTokensWithOTP(credential, loginOTP, loginUid);
}
else {
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserTokens(credential, loginUid);
call = RetrofitClient.getApiInterface(appCtx).getUserTokens(credential, loginUid);
}
call.enqueue(new Callback<List<UserTokens>>() {
@ -431,7 +429,9 @@ public class LoginActivity extends BaseActivity {
if(response.code() == 200) {
assert userTokens != null;
for(UserTokens t : userTokens) {
if(t.getName().equals(tokenName)) {
// this app had created an token on this instance before
@ -440,13 +440,14 @@ public class LoginActivity extends BaseActivity {
Call<Void> delcall;
if(loginOTP != 0) {
delcall = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface()
delcall = RetrofitClient.getApiInterface(ctx)
.deleteTokenWithOTP(credential, loginOTP, loginUid, t.getId());
}
else {
delcall = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().deleteToken(credential, loginUid, t.getId());
delcall = RetrofitClient.getApiInterface(ctx).deleteToken(credential, loginUid, t.getId());
}
delcall.enqueue(new Callback<Void>() {
@Override
@ -454,13 +455,12 @@ public class LoginActivity extends BaseActivity {
if(response.code() == 204) {
setupToken(instanceUrl, loginUid, loginPass, loginOTP, tokenName);
setupToken(loginUid, loginPass, loginOTP, tokenName);
}
else {
Toasty.error(ctx, getResources().getString(R.string.genericApiStatusError) + response.code());
enableProcessButton();
}
}
@ -470,20 +470,18 @@ public class LoginActivity extends BaseActivity {
Log.e("onFailure-login", t.toString());
Toasty.error(ctx, getResources().getString(R.string.malformedJson));
enableProcessButton();
}
});
return;
}
}
setupToken(instanceUrl, loginUid, loginPass, loginOTP, tokenName);
setupToken(loginUid, loginPass, loginOTP, tokenName);
}
else {
Toasty.error(ctx, getResources().getString(R.string.genericApiStatusError) + response.code());
enableProcessButton();
}
}
@ -493,13 +491,12 @@ public class LoginActivity extends BaseActivity {
Log.e("onFailure-login", t.toString());
Toasty.error(ctx, getResources().getString(R.string.malformedJson));
enableProcessButton();
}
});
}
private void setupToken(final String instanceUrl, final String loginUid, final String loginPass, final int loginOTP, final String tokenName) {
private void setupToken(final String loginUid, final String loginPass, final int loginOTP, final String tokenName) {
final String credential = Credentials.basic(loginUid, loginPass, StandardCharsets.UTF_8);
@ -508,12 +505,13 @@ public class LoginActivity extends BaseActivity {
if(loginOTP != 0) {
callCreateToken = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface()
callCreateToken = RetrofitClient.getApiInterface(ctx)
.createNewTokenWithOTP(credential, loginOTP, loginUid, createUserToken);
}
else {
callCreateToken = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().createNewToken(credential, loginUid, createUserToken);
callCreateToken = RetrofitClient.getApiInterface(ctx)
.createNewToken(credential, loginUid, createUserToken);
}
callCreateToken.enqueue(new Callback<UserTokens>() {
@ -528,7 +526,7 @@ public class LoginActivity extends BaseActivity {
if(!newToken.getSha1().equals("")) {
Call<UserInfo> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface()
Call<UserInfo> call = RetrofitClient.getApiInterface(ctx)
.getUserInfo("token " + newToken.getSha1());
call.enqueue(new Callback<UserInfo>() {
@ -541,6 +539,7 @@ public class LoginActivity extends BaseActivity {
switch(response.code()) {
case 200:
assert userDetails != null;
tinyDB.remove("loginPass");
tinyDB.putBoolean("loggedInMode", true);
@ -549,39 +548,37 @@ public class LoginActivity extends BaseActivity {
tinyDB.putString(loginUid + "-token-last-eight", newToken.getToken_last_eight());
// insert new account to db if does not exist
String accountName = userDetails.getUsername() + "@" + instanceUrl;
UserAccountsApi userAccountsApi = new UserAccountsApi(ctx);
int checkAccount = userAccountsApi.getCount(accountName);
String accountName = userDetails.getUsername() + "@" + TinyDB.getInstance(ctx).getString("instanceUrl");
UserAccountsApi userAccountsApi = BaseApi.getInstance(ctx, UserAccountsApi.class);
boolean userAccountExists = userAccountsApi.userAccountExists(accountName);
long accountId;
if(checkAccount == 0) {
if(!userAccountExists) {
accountId = userAccountsApi
.insertNewAccount(accountName, instanceUrl, userDetails.getUsername(), newToken.getSha1(), "");
.createNewAccount(accountName, TinyDB.getInstance(ctx).getString("instanceUrl"), userDetails.getUsername(), newToken.getSha1(), "");
tinyDB.putInt("currentActiveAccountId", (int) accountId);
}
else {
userAccountsApi.updateTokenByAccountName(accountName, newToken.getSha1());
UserAccount data = userAccountsApi.getAccountData(accountName);
UserAccount data = userAccountsApi.getAccountByName(accountName);
tinyDB.putInt("currentActiveAccountId", data.getAccountId());
}
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
break;
case 401:
Toasty.error(ctx, getResources().getString(R.string.unauthorizedApiError));
enableProcessButton();
break;
default:
Toasty.error(ctx, getResources().getString(R.string.genericApiStatusError) + response.code());
enableProcessButton();
}
}
@Override
@ -590,7 +587,6 @@ public class LoginActivity extends BaseActivity {
Log.e("onFailure", t.toString());
Toasty.error(ctx, getResources().getString(R.string.genericError));
enableProcessButton();
}
});
}
@ -599,7 +595,6 @@ public class LoginActivity extends BaseActivity {
Toasty.error(ctx, getResources().getString(R.string.genericApiStatusError) + responseCreate.code());
enableProcessButton();
}
}
@ -615,17 +610,21 @@ public class LoginActivity extends BaseActivity {
private void loadDefaults() {
if(tinyDB.getString("loginType").equals(LoginType.BASIC.name().toLowerCase())) {
loginMethod.check(R.id.loginUsernamePassword);
}
else {
loginMethod.check(R.id.loginToken);
}
if(!tinyDB.getString("instanceUrlRaw").equals("")) {
instanceUrlET.setText(tinyDB.getString("instanceUrlRaw"));
}
if(!tinyDB.getString("loginUid").equals("")) {
loginUidET.setText(tinyDB.getString("loginUid"));
}
@ -636,9 +635,11 @@ public class LoginActivity extends BaseActivity {
}
if(!tinyDB.getString("uniqueAppId").isEmpty()) {
device_id = tinyDB.getString("uniqueAppId");
}
else {
device_id = UUID.randomUUID().toString();
tinyDB.putString("uniqueAppId", device_id);
}

View File

@ -3,15 +3,13 @@ package org.mian.gitnex.activities;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
@ -19,18 +17,24 @@ import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.cardview.widget.CardView;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.navigation.NavigationView;
import org.gitnex.tea4j.models.GiteaVersion;
import org.gitnex.tea4j.models.NotificationCount;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.UserAccountsNavAdapter;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.databinding.ActivityMainBinding;
import org.mian.gitnex.fragments.AdministrationFragment;
import org.mian.gitnex.fragments.BottomSheetDraftsFragment;
import org.mian.gitnex.fragments.DraftsFragment;
@ -38,7 +42,7 @@ import org.mian.gitnex.fragments.ExploreFragment;
import org.mian.gitnex.fragments.MyRepositoriesFragment;
import org.mian.gitnex.fragments.NotificationsFragment;
import org.mian.gitnex.fragments.OrganizationsFragment;
import org.mian.gitnex.fragments.ProfileFragment;
import org.mian.gitnex.fragments.MyProfileFragment;
import org.mian.gitnex.fragments.RepositoriesFragment;
import org.mian.gitnex.fragments.SettingsFragment;
import org.mian.gitnex.fragments.StarredRepositoriesFragment;
@ -52,14 +56,9 @@ import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.models.NotificationCount;
import org.mian.gitnex.models.UserInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import eightbitlab.com.blurview.BlurView;
import eightbitlab.com.blurview.RenderScriptBlur;
import jp.wasabeef.picasso.transformations.BlurTransformation;
import retrofit2.Call;
import retrofit2.Callback;
@ -70,19 +69,9 @@ import retrofit2.Callback;
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener, BottomSheetDraftsFragment.BottomSheetListener {
private DrawerLayout drawer;
private BlurView blurView;
private TextView userFullName;
private TextView userEmail;
private ImageView userAvatar;
private ImageView userAvatarBackground;
private ViewGroup navHeaderFrame;
private TextView toolbarTitle;
final Context ctx = this;
private Context appCtx;
private static TinyDB tinyDb;
private Typeface myTypeface;
private String instanceUrl;
private String loginUid;
private String instanceToken;
@ -90,60 +79,51 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
private MenuItem navNotifications;
private TextView notificationCounter;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_main;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
tinyDb.putBoolean("noConnection", false);
ActivityMainBinding activityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(activityMainBinding.getRoot());
Intent mainIntent = getIntent();
String launchFragment = mainIntent.getStringExtra("launchFragment");
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
// DO NOT MOVE
if(mainIntent.hasExtra("switchAccountId") &&
AppUtil.switchToAccount(ctx, BaseApi.getInstance(ctx, UserAccountsApi.class)
.getAccountById(mainIntent.getIntExtra("switchAccountId", 0)))) {
mainIntent.removeExtra("switchAccountId");
recreate();
return;
if(tinyDb.getString("dateFormat").isEmpty()) {
tinyDb.putString("dateFormat", "pretty");
}
// DO NOT MOVE
if(tinyDb.getString("codeBlockStr").isEmpty()) {
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorLightGreen));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
}
tinyDB.putBoolean("noConnection", false);
if(tinyDb.getString("enableCounterIssueBadgeInit").isEmpty()) {
tinyDb.putBoolean("enableCounterIssueBadge", true);
}
if(tinyDb.getString("homeScreenStr").isEmpty()) {
tinyDb.putInt("homeScreenId", 0);
}
loginUid = tinyDB.getString("loginUid");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
if(!tinyDb.getBoolean("loggedInMode")) {
if(!tinyDB.getBoolean("loggedInMode")) {
logout(this, ctx);
return;
}
if(tinyDb.getInt("currentActiveAccountId") <= 0) {
AlertDialogs.forceLogoutDialog(ctx, getResources().getString(R.string.forceLogoutDialogHeader), getResources().getString(R.string.forceLogoutDialogDescription), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
if(tinyDB.getInt("currentActiveAccountId", -1) <= 0) {
AlertDialogs.forceLogoutDialog(ctx,
getResources().getString(R.string.forceLogoutDialogHeader),
getResources().getString(R.string.forceLogoutDialogDescription), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
Toolbar toolbar = findViewById(R.id.toolbar);
toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
Toolbar toolbar = activityMainBinding.toolbar;
toolbarTitle = activityMainBinding.toolbarTitle;
switch(tinyDb.getInt("customFontId", -1)) {
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/roboto.ttf");
@ -183,7 +163,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
else if(fragmentById instanceof NotificationsFragment) {
toolbarTitle.setText(R.string.pageTitleNotifications);
}
else if(fragmentById instanceof ProfileFragment) {
else if(fragmentById instanceof MyProfileFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
}
else if(fragmentById instanceof DraftsFragment) {
@ -196,17 +176,17 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
toolbarTitle.setText(getResources().getString(R.string.pageTitleUserAccounts));
}
getNotificationsCount(instanceUrl, instanceToken);
getNotificationsCount(instanceToken);
drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
drawer = activityMainBinding.drawerLayout;
NavigationView navigationView = activityMainBinding.navView;
navigationView.setNavigationItemSelectedListener(this);
hView = navigationView.getHeaderView(0);
Menu menu = navigationView.getMenu();
navNotifications = menu.findItem(R.id.nav_notifications);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigationDrawerOpen, R.string.navigationDrawerClose);
drawer.addDrawerListener(toggle);
drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
@ -214,46 +194,37 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
@Override
public void onDrawerOpened(@NonNull View drawerView) {
getNotificationsCount(instanceUrl, instanceToken);
}
if(tinyDB.getBoolean("noConnection")) {
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
if(tinyDb.getBoolean("noConnection")) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
tinyDb.putBoolean("noConnection", false);
tinyDB.putBoolean("noConnection", false);
}
String userEmailNav = tinyDb.getString("userEmail");
String userFullNameNav = tinyDb.getString("userFullname");
String userAvatarNav = tinyDb.getString("userAvatar");
String userEmailNav = tinyDB.getString("userEmail");
String userFullNameNav = tinyDB.getString("userFullname");
String userAvatarNav = tinyDB.getString("userAvatar");
blurView = hView.findViewById(R.id.blurView);
userEmail = hView.findViewById(R.id.userEmail);
userFullName = hView.findViewById(R.id.userFullname);
userAvatar = hView.findViewById(R.id.userAvatar);
userAvatarBackground = hView.findViewById(R.id.userAvatarBackground);
navHeaderFrame = hView.findViewById(R.id.navHeaderFrame);
TextView userEmail = hView.findViewById(R.id.userEmail);
TextView userFullName = hView.findViewById(R.id.userFullname);
ImageView userAvatar = hView.findViewById(R.id.userAvatar);
ImageView userAvatarBackground = hView.findViewById(R.id.userAvatarBackground);
CardView navRecyclerViewFrame = hView.findViewById(R.id.userAccountsFrame);
List<UserAccount> userAccountsList;
userAccountsList = new ArrayList<>();
List<UserAccount> userAccountsList = new ArrayList<>();
UserAccountsApi userAccountsApi;
userAccountsApi = new UserAccountsApi(ctx);
userAccountsApi = BaseApi.getInstance(ctx, UserAccountsApi.class);
RecyclerView navRecyclerViewUserAccounts = hView.findViewById(R.id.navRecyclerViewUserAccounts);
RecyclerView navRecyclerViewUserAccounts = hView.findViewById(R.id.userAccounts);
UserAccountsNavAdapter adapterUserAccounts;
adapterUserAccounts = new UserAccountsNavAdapter(ctx, userAccountsList, drawer, toolbarTitle);
userAccountsApi.getAllAccounts().observe((AppCompatActivity) ctx, userAccounts -> {
if(userAccounts.size() > 0) {
userAccountsList.addAll(userAccounts);
navRecyclerViewUserAccounts.setAdapter(adapterUserAccounts);
navRecyclerViewFrame.setVisibility(View.VISIBLE);
}
});
userEmail.setTypeface(myTypeface);
@ -264,56 +235,55 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
}
if(!userFullNameNav.equals("")) {
userFullName.setText(userFullNameNav);
userFullName.setText(Html.fromHtml(userFullNameNav));
}
if(!userAvatarNav.equals("")) {
int avatarRadius = AppUtil.getPixelsFromDensity(ctx, 3);
PicassoService.getInstance(ctx).get()
.load(userAvatarNav)
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(8, 0))
.transform(new RoundedTransformation(avatarRadius, 0))
.resize(160, 160)
.centerCrop().into(userAvatar);
PicassoService.getInstance(ctx).get()
.load(userAvatarNav)
.transform(new BlurTransformation(ctx))
.into(userAvatarBackground, new com.squareup.picasso.Callback() {
@Override
public void onSuccess() {
int textColor = new ColorInverter().getImageViewContrastColor(userAvatarBackground);
userFullName.setTextColor(textColor);
userEmail.setTextColor(textColor);
blurView.setupWith(navHeaderFrame)
.setBlurAlgorithm(new RenderScriptBlur(ctx))
.setBlurRadius(5)
.setHasFixedTransformationMatrix(false);
}
@Override
public void onError(Exception e) {}
@Override public void onError(Exception e) {}
});
}
userAvatar.setOnClickListener(v -> {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
drawer.closeDrawers();
});
String currentVersion = tinyDb.getString("giteaVersion");
getNotificationsCount(instanceToken);
}
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
navigationView.getMenu().findItem(R.id.nav_administration).setVisible(tinyDB.getBoolean("userIsAdmin"));
navigationView.getMenu().findItem(R.id.nav_notifications).setVisible(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.3"));
navigationView.getMenu().findItem(R.id.nav_administration).setVisible(tinyDb.getBoolean("userIsAdmin"));
navigationView.getMenu().findItem(R.id.nav_notifications).setVisible(new Version(currentVersion).higherOrEqual("1.12.3"));
}
@Override
@ -327,6 +297,8 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
toggle.syncState();
toolbar.setNavigationIcon(R.drawable.ic_menu);
String launchFragment = mainIntent.getStringExtra("launchFragment");
if(launchFragment != null) {
mainIntent.removeExtra("launchFragment");
@ -344,7 +316,6 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications);
return;
}
}
@ -369,26 +340,36 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
case "notification":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications);
setActionBarTitle(getResources().getString(R.string.pageTitleNotifications));
return;
case "explore":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
navigationView.setCheckedItem(R.id.nav_explore);
return;
case "profile":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
return;
case "admin":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AdministrationFragment()).commit();
navigationView.setCheckedItem(R.id.nav_administration);
return;
}
}
if(savedInstanceState == null) {
if(!new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.3")) {
if(tinyDb.getInt("homeScreenId") == 7) {
tinyDb.putInt("homeScreenId", 0);
if(!new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.3")) {
if(tinyDB.getInt("homeScreenId") == 7) {
tinyDB.putInt("homeScreenId", 0);
}
}
switch(tinyDb.getInt("homeScreenId")) {
switch(tinyDB.getInt("homeScreenId")) {
case 1:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
@ -410,7 +391,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
case 4:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
break;
@ -437,44 +418,32 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
break;
}
}
if(!connToInternet) {
if(!tinyDb.getBoolean("noConnection")) {
if(!tinyDB.getBoolean("noConnection")) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
}
tinyDb.putBoolean("noConnection", true);
tinyDB.putBoolean("noConnection", true);
}
else {
loadUserInfo(instanceUrl, instanceToken, loginUid);
giteaVersion(instanceUrl);
tinyDb.putBoolean("noConnection", false);
loadUserInfo(instanceToken, loginUid);
giteaVersion();
tinyDB.putBoolean("noConnection", false);
}
// Changelog popup
int versionCode = 0;
int versionCode = AppUtil.getAppBuildNo(appCtx);
try {
if(versionCode > tinyDB.getInt("versionCode")) {
PackageInfo packageInfo = appCtx.getPackageManager().getPackageInfo(appCtx.getPackageName(), 0);
versionCode = packageInfo.versionCode;
}
catch(PackageManager.NameNotFoundException e) {
Log.e("changelogDialog", Objects.requireNonNull(e.getMessage()));
}
if(versionCode > tinyDb.getInt("versionCode")) {
tinyDb.putInt("versionCode", versionCode);
tinyDb.putBoolean("versionFlag", true);
tinyDB.putInt("versionCode", versionCode);
tinyDB.putBoolean("versionFlag", true);
ChangeLog changelogDialog = new ChangeLog(this);
changelogDialog.showDialog();
@ -489,7 +458,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
@Override
public void onButtonClicked(String text) {
TinyDB tinyDb = new TinyDB(ctx);
TinyDB tinyDb = TinyDB.getInstance(ctx);
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
if("deleteDrafts".equals(text)) {
@ -513,14 +482,15 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
})
.setNeutralButton(R.string.cancelButton, null).show();
}
else {
Toasty.error(ctx, getResources().getString(R.string.genericError));
}
}
else {
Toasty.error(ctx, getResources().getString(R.string.genericError));
}
@ -532,74 +502,74 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
public void onBackPressed() {
if(drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
else {
super.onBackPressed();
}
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
switch(menuItem.getItemId()) {
int id = 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;
if(id == R.id.nav_home) {
case R.id.nav_organizations:
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
break;
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
}
else if(id == R.id.nav_organizations) {
case R.id.nav_profile:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
break;
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
}
else if(id == R.id.nav_profile) {
case R.id.nav_repositories:
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
break;
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyProfileFragment()).commit();
}
else if(id == R.id.nav_repositories) {
case R.id.nav_settings:
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new SettingsFragment()).commit();
break;
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
}
else if(id == R.id.nav_settings) {
case R.id.nav_logout:
logout(this, ctx);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
break;
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new SettingsFragment()).commit();
}
else if(id == R.id.nav_logout) {
case R.id.nav_starred_repos:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
break;
logout(this, ctx);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
else if(id == R.id.nav_starred_repos) {
case R.id.nav_explore:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
break;
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
}
else if(id == R.id.nav_explore) {
case R.id.nav_notifications:
toolbarTitle.setText(R.string.pageTitleNotifications);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
break;
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
}
else if(id == R.id.nav_notifications) {
case R.id.nav_comments_draft:
toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit();
break;
toolbarTitle.setText(R.string.pageTitleNotifications);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
}
else if(id == R.id.nav_comments_draft) {
case R.id.nav_administration:
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AdministrationFragment()).commit();
break;
toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit();
}
else if(id == R.id.nav_administration) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AdministrationFragment()).commit();
}
drawer.closeDrawer(GravityCompat.START);
@ -608,13 +578,14 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
public static void logout(Activity activity, Context ctx) {
tinyDb.putBoolean("loggedInMode", false);
tinyDb.remove("basicAuthPassword");
tinyDb.putBoolean("basicAuthFlag", false);
TinyDB tinyDB = TinyDB.getInstance(ctx);
tinyDB.putBoolean("loggedInMode", false);
tinyDB.remove("basicAuthPassword");
tinyDB.putBoolean("basicAuthFlag", false);
//tinyDb.clear();
activity.finish();
ctx.startActivity(new Intent(ctx, LoginActivity.class));
}
@Override
@ -623,53 +594,43 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
int id = item.getItemId();
if(id == R.id.genericMenu) {
BottomSheetDraftsFragment bottomSheet = new BottomSheetDraftsFragment();
bottomSheet.show(getSupportFragmentManager(), "draftsBottomSheet");
return true;
}
return super.onOptionsItemSelected(item);
}
private void giteaVersion(final String instanceUrl) {
final TinyDB tinyDb = new TinyDB(appCtx);
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
Call<GiteaVersion> callVersion = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getGiteaVersionWithToken(token);
private void giteaVersion() {
Call<GiteaVersion> callVersion = RetrofitClient.getApiInterface(ctx).getGiteaVersionWithToken(Authorization.get(ctx));
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());
if(responseVersion.code() == 200 && responseVersion.body() != null) {
String version = responseVersion.body().getVersion();
tinyDB.putString("giteaVersion", version);
BaseApi.getInstance(ctx, UserAccountsApi.class).updateServerVersion(version, tinyDB.getInt("currentActiveAccountId"));
}
}
@Override
public void onFailure(@NonNull Call<GiteaVersion> callVersion, @NonNull Throwable t) {
Log.e("onFailure-version", t.toString());
}
});
}
private void loadUserInfo(String instanceUrl, String token, String loginUid) {
private void loadUserInfo(String token, String loginUid) {
final TinyDB tinyDb = new TinyDB(appCtx);
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
Call<UserInfo> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserInfo(Authorization.returnAuthentication(ctx, loginUid, token));
Call<UserInfo> call = RetrofitClient.getApiInterface(ctx).getUserInfo(Authorization.get(ctx));
call.enqueue(new Callback<UserInfo>() {
@ -685,6 +646,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
assert userDetails != null;
if(userDetails.getIs_admin() != null) {
tinyDb.putBoolean("userIsAdmin", userDetails.getIs_admin());
}
@ -692,9 +654,11 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
tinyDb.putInt("userId", userDetails.getId());
if(!userDetails.getFullname().equals("")) {
tinyDb.putString("userFullname", userDetails.getFullname());
}
else {
tinyDb.putString("userFullname", userDetails.getLogin());
}
@ -702,9 +666,11 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
tinyDb.putString("userAvatar", userDetails.getAvatar());
if(userDetails.getLang() != null) {
tinyDb.putString("userLang", userDetails.getLang());
}
else {
tinyDb.putString("userLang", "");
}
}
@ -712,15 +678,12 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
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 {
String toastError = getResources().getString(R.string.genericApiStatusError) + response.code();
Toasty.error(ctx, toastError);
}
}
@Override
@ -732,9 +695,9 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
}
private void getNotificationsCount(String instanceUrl, String token) {
private void getNotificationsCount(String token) {
Call<NotificationCount> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkUnreadNotifications(token);
Call<NotificationCount> call = RetrofitClient.getApiInterface(ctx).checkUnreadNotifications(token);
call.enqueue(new Callback<NotificationCount>() {

View File

@ -9,20 +9,19 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.gitnex.tea4j.models.MergePullRequest;
import org.gitnex.tea4j.models.MergePullRequestSpinner;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.PullRequestActions;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityMergePullRequestBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.MergePullRequest;
import org.mian.gitnex.models.MergePullRequestSpinner;
import java.util.ArrayList;
import java.util.Objects;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
@ -33,13 +32,7 @@ import retrofit2.Callback;
public class MergePullRequestActivity extends BaseActivity {
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
private String instanceUrl;
private String loginUid;
private String instanceToken;
private String repoOwner;
private String repoName;
private int prIndex;
@ -48,32 +41,20 @@ public class MergePullRequestActivity extends BaseActivity {
private String Do;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_merge_pull_request;
}
@SuppressLint("SetTextI18n")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
viewBinding = ActivityMergePullRequestBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
setContentView(viewBinding.getRoot());
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repoOwner = parts[0];
repoName = parts[1];
prIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
prIndex = Integer.parseInt(tinyDB.getString("issueNumber"));
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
@ -85,32 +66,37 @@ public class MergePullRequestActivity extends BaseActivity {
setMergeAdapter();
if(!tinyDb.getString("issueTitle").isEmpty()) {
if(!tinyDB.getString("issueTitle").isEmpty()) {
viewBinding.toolbarTitle.setText(tinyDb.getString("issueTitle"));
viewBinding.mergeTitle.setText(tinyDb.getString("issueTitle") + " (#" + tinyDb.getString("issueNumber") + ")");
viewBinding.toolbarTitle.setText(tinyDB.getString("issueTitle"));
viewBinding.mergeTitle.setText(tinyDB.getString("issueTitle") + " (#" + tinyDB.getString("issueNumber") + ")");
}
initCloseListener();
viewBinding.close.setOnClickListener(onClickListener);
// if gitea version is greater/equal(1.12.0) than user installed version (installed.higherOrEqual(compareVer))
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
viewBinding.deleteBranch.setVisibility(View.VISIBLE);
}
if(tinyDb.getString("prMergeable").equals("false")) {
if(tinyDB.getString("prMergeable").equals("false")) {
disableProcessButton();
viewBinding.mergeInfoDisabledMessage.setVisibility(View.VISIBLE);
}
else {
viewBinding.mergeInfoDisabledMessage.setVisibility(View.GONE);
}
if(tinyDb.getString("prIsFork").equals("true")) {
if(tinyDB.getString("prIsFork").equals("true")) {
viewBinding.deleteBranchForkInfo.setVisibility(View.VISIBLE);
}
else {
viewBinding.deleteBranchForkInfo.setVisibility(View.GONE);
}
@ -133,7 +119,8 @@ public class MergePullRequestActivity extends BaseActivity {
mergeList.add(new MergePullRequestSpinner("rebase", getResources().getString(R.string.mergeOptionRebase)));
mergeList.add(new MergePullRequestSpinner("rebase-merge", getResources().getString(R.string.mergeOptionRebaseCommit)));
// squash merge works only on gitea > v1.11.4 due to a bug
if(new Version(tinyDb.getString("giteaVersion")).higher("1.11.4")) {
if(new Version(tinyDB.getString("giteaVersion")).higher("1.11.4")) {
mergeList.add(new MergePullRequestSpinner("squash", getResources().getString(R.string.mergeOptionSquash)));
}
@ -152,7 +139,7 @@ public class MergePullRequestActivity extends BaseActivity {
onClickListener = view -> finish();
}
private View.OnClickListener mergePullRequest = v -> processMergePullRequest();
private final View.OnClickListener mergePullRequest = v -> processMergePullRequest();
private void processMergePullRequest() {
@ -183,43 +170,43 @@ public class MergePullRequestActivity extends BaseActivity {
MergePullRequest mergePR = new MergePullRequest(Do, mergePRDT, mergeTitle);
Call<ResponseBody> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().mergePullRequest(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, prIndex, mergePR);
Call<Void> call = RetrofitClient.getApiInterface(ctx).mergePullRequest(Authorization.get(ctx), repoOwner, repoName, prIndex, mergePR);
call.enqueue(new Callback<ResponseBody>() {
call.enqueue(new Callback<Void>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
public void onResponse(@NonNull Call<Void> call, @NonNull retrofit2.Response<Void> response) {
if(response.code() == 200) {
if(deleteBranch) {
if(tinyDb.getString("prIsFork").equals("true")) {
if(tinyDB.getString("prIsFork").equals("true")) {
String repoFullName = tinyDb.getString("prForkFullName");
String repoFullName = tinyDB.getString("prForkFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
deleteBranchFunction(repoOwner, repoName);
PullRequestActions.deleteHeadBranch(ctx, repoOwner, repoName, tinyDB.getString("prHeadBranch"), false);
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
tinyDB.putBoolean("prMerged", true);
tinyDB.putBoolean("resumePullRequests", true);
finish();
}
else {
String repoFullName = tinyDb.getString("repoFullName");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
deleteBranchFunction(repoOwner, repoName);
PullRequestActions.deleteHeadBranch(ctx, repoOwner, repoName, tinyDB.getString("prHeadBranch"), false);
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
tinyDB.putBoolean("prMerged", true);
tinyDB.putBoolean("resumePullRequests", true);
finish();
}
@ -227,8 +214,8 @@ public class MergePullRequestActivity extends BaseActivity {
else {
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
tinyDB.putBoolean("prMerged", true);
tinyDB.putBoolean("resumePullRequests", true);
finish();
}
@ -243,6 +230,11 @@ public class MergePullRequestActivity extends BaseActivity {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.mergePR404ErrorMsg));
}
else if(response.code() == 405) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.mergeNotAllowed));;
}
else {
enableProcessButton();
@ -252,39 +244,7 @@ public class MergePullRequestActivity extends BaseActivity {
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void deleteBranchFunction(String repoOwner, String repoName) {
String branchName = tinyDb.getString("prHeadBranch");
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.deleteBranch(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 204) {
Log.i("deleteBranch", "Branch deleted successfully");
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();

View File

@ -11,14 +11,15 @@ import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.gitnex.tea4j.models.AddEmail;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityProfileEmailBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.AddEmail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -29,32 +30,27 @@ import retrofit2.Callback;
* Author M M Arif
*/
public class ProfileEmailActivity extends BaseActivity {
public class MyProfileEmailActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private EditText userEmail;
final Context ctx = this;
private Context appCtx;
private Button addEmailButton;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_profile_email;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
ActivityProfileEmailBinding activityProfileEmailBinding = ActivityProfileEmailBinding.inflate(getLayoutInflater());
setContentView(activityProfileEmailBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
ImageView closeActivity = findViewById(R.id.close);
userEmail = findViewById(R.id.userEmail);
addEmailButton = findViewById(R.id.addEmailButton);
ImageView closeActivity = activityProfileEmailBinding.close;
userEmail = activityProfileEmailBinding.userEmail;
addEmailButton = activityProfileEmailBinding.addEmailButton;
userEmail.requestFocus();
assert imm != null;
@ -73,19 +69,11 @@ public class ProfileEmailActivity extends BaseActivity {
}
private View.OnClickListener addEmailListener = new View.OnClickListener() {
public void onClick(View v) {
processAddNewEmail();
}
};
private final View.OnClickListener addEmailListener = v -> processAddNewEmail();
private void processAddNewEmail() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String newUserEmail = userEmail.getText().toString().trim();
@ -93,39 +81,34 @@ public class ProfileEmailActivity extends BaseActivity {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newUserEmail.equals("")) {
Toasty.error(ctx, getString(R.string.emailErrorEmpty));
return;
}
else if(!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) {
Toasty.warning(ctx, getString(R.string.emailErrorInvalid));
return;
}
List<String> newEmailList = new ArrayList<>(Arrays.asList(newUserEmail.split(",")));
disableProcessButton();
addNewEmail(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), newEmailList);
addNewEmail(Authorization.get(ctx), newEmailList);
}
private void addNewEmail(final String instanceUrl, final String token, List<String> newUserEmail) {
private void addNewEmail(final String token, List<String> newUserEmail) {
AddEmail addEmailFunc = new AddEmail(newUserEmail);
final TinyDB tinyDb = new TinyDB(appCtx);
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(appCtx)
.addNewEmail(token, addEmailFunc);
call.enqueue(new Callback<JsonElement>() {
@ -139,7 +122,6 @@ public class ProfileEmailActivity extends BaseActivity {
tinyDb.putBoolean("emailsRefresh", true);
enableProcessButton();
finish();
}
else if(response.code() == 401) {
@ -148,37 +130,32 @@ public class ProfileEmailActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else if(response.code() == 422) {
enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.emailErrorInUse));
}
else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}

View File

@ -25,8 +25,9 @@ public class OpenRepoInBrowserActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
try {
@ -46,9 +47,9 @@ public class OpenRepoInBrowserActivity extends AppCompatActivity {
}
catch(URISyntaxException e) {
Toasty.error(appCtx, getString(R.string.genericError));
}
}
}

View File

@ -23,9 +23,9 @@ import org.mian.gitnex.R;
import org.mian.gitnex.fragments.BottomSheetOrganizationFragment;
import org.mian.gitnex.fragments.MembersByOrgFragment;
import org.mian.gitnex.fragments.OrganizationInfoFragment;
import org.mian.gitnex.fragments.OrganizationLabelsFragment;
import org.mian.gitnex.fragments.RepositoriesByOrgFragment;
import org.mian.gitnex.fragments.TeamsByOrgFragment;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.Objects;
import io.mikael.urlbuilder.UrlBuilder;
@ -36,27 +36,17 @@ import io.mikael.urlbuilder.UrlBuilder;
public class OrganizationDetailActivity extends BaseActivity implements BottomSheetOrganizationFragment.BottomSheetListener {
final Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_org_detail;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = new TinyDB(appCtx);
String orgName = tinyDb.getString("orgName");
setContentView(R.layout.activity_org_detail);
String orgName = tinyDB.getString("orgName");
Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
TextView toolbarTitle = findViewById(R.id.toolbar_title);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(orgName);
@ -71,20 +61,20 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
Typeface myTypeface;
switch(tinyDb.getInt("customFontId", -1)) {
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
break;
}
toolbarTitle.setTypeface(myTypeface);
@ -92,12 +82,18 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
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);
}
}
@ -105,7 +101,6 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
}
@ -122,18 +117,21 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
int id = item.getItemId();
switch (id) {
case android.R.id.home:
finish();
return true;
case R.id.repoMenu:
BottomSheetOrganizationFragment bottomSheet = new BottomSheetOrganizationFragment();
bottomSheet.show(getSupportFragmentManager(), "orgBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
if(id == android.R.id.home) {
finish();
return true;
}
else if(id == R.id.repoMenu) {
BottomSheetOrganizationFragment bottomSheet = new BottomSheetOrganizationFragment();
bottomSheet.show(getSupportFragmentManager(), "orgBottomSheet");
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
@Override
@ -142,20 +140,27 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
switch (text) {
case "repository":
tinyDb.putBoolean("organizationAction", true);
tinyDB.putBoolean("organizationAction", true);
startActivity(new Intent(OrganizationDetailActivity.this, CreateRepoActivity.class));
break;
case "label":
Intent intent = new Intent(ctx, CreateLabelActivity.class);
intent.putExtra("orgName", getIntent().getStringExtra("orgName"));
intent.putExtra("type", "org");
ctx.startActivity(intent);
break;
case "team":
startActivity(new Intent(OrganizationDetailActivity.this, CreateTeamByOrgActivity.class));
break;
case "copyOrgUrl":
String url = UrlBuilder.fromString(tinyDb.getString("instanceUrl"))
String url = UrlBuilder.fromString(tinyDB.getString("instanceUrl"))
.withPath("/")
.toString();
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("orgUrl", url + tinyDb.getString("orgName"));
ClipData clip = ClipData.newPlainText("orgUrl", url + tinyDB.getString("orgName"));
assert clipboard != null;
clipboard.setPrimaryClip(clip);
Toasty.info(ctx, ctx.getString(R.string.copyIssueUrlToastMsg));
@ -175,30 +180,39 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
String orgName;
if(getIntent().getStringExtra("orgName") != null || !Objects.equals(getIntent().getStringExtra("orgName"), "")) {
orgName = getIntent().getStringExtra("orgName");
}
else {
orgName = tinyDb.getString("orgName");
orgName = tinyDB.getString("orgName");
}
Fragment fragment = null;
switch (position) {
case 0: // info
return OrganizationInfoFragment.newInstance(orgName);
case 1: // repos
return RepositoriesByOrgFragment.newInstance(orgName);
case 2: // teams
return RepositoriesByOrgFragment.newInstance(orgName);
case 2: // labels
return OrganizationLabelsFragment.newInstance(orgName);
case 3: // teams
return TeamsByOrgFragment.newInstance(orgName);
case 3: // members
case 4: // members
return MembersByOrgFragment.newInstance(orgName);
}
return fragment;
}
@Override
public int getCount() {
return 4;
return 5;
}
}
}

View File

@ -1,6 +1,5 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
@ -15,6 +14,7 @@ import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.TeamMembersByOrgAdapter;
import org.mian.gitnex.databinding.ActivityOrgTeamMembersBinding;
import org.mian.gitnex.fragments.BottomSheetOrganizationTeamsFragment;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
@ -33,85 +33,78 @@ public class OrganizationTeamMembersActivity extends BaseActivity implements Bot
private GridView mGridView;
private ProgressBar progressBar;
final Context ctx = this;
private Context appCtx;
private String teamId;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_org_team_members;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
Toolbar toolbar = findViewById(R.id.toolbar);
ActivityOrgTeamMembersBinding activityOrgTeamMembersBinding = ActivityOrgTeamMembersBinding.inflate(getLayoutInflater());
setContentView(activityOrgTeamMembersBinding.getRoot());
Toolbar toolbar = activityOrgTeamMembersBinding.toolbar;
setSupportActionBar(toolbar);
TinyDB tinyDb = new TinyDB(appCtx);
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);
noDataMembers = findViewById(R.id.noDataMembers);
mGridView = findViewById(R.id.gridView);
progressBar = findViewById(R.id.progressBar);
ImageView closeActivity = activityOrgTeamMembersBinding.close;
TextView toolbarTitle = activityOrgTeamMembersBinding.toolbarTitle;
noDataMembers = activityOrgTeamMembersBinding.noDataMembers;
mGridView = activityOrgTeamMembersBinding.gridView;
progressBar = activityOrgTeamMembersBinding.progressBar;
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(getIntent().getStringExtra("teamTitle") != null && !Objects.requireNonNull(getIntent().getStringExtra("teamTitle")).equals("")) {
toolbarTitle.setText(getIntent().getStringExtra("teamTitle"));
toolbarTitle.setText(getIntent().getStringExtra("teamTitle"));
}
else {
toolbarTitle.setText(R.string.orgTeamMembers);
toolbarTitle.setText(R.string.orgTeamMembers);
}
if(getIntent().getStringExtra("teamId") != null && !Objects.requireNonNull(getIntent().getStringExtra("teamId")).equals("")){
teamId = getIntent().getStringExtra("teamId");
teamId = getIntent().getStringExtra("teamId");
}
else {
teamId = "0";
teamId = "0";
}
assert teamId != null;
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), Integer.parseInt(teamId));
fetchDataAsync(Authorization.get(ctx), Integer.parseInt(teamId));
}
@Override
public void onResume() {
super.onResume();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
TinyDB tinyDb = TinyDB.getInstance(appCtx);
if(tinyDb.getBoolean("teamActionFlag")) {
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), Integer.parseInt(teamId));
fetchDataAsync(Authorization.get(ctx), Integer.parseInt(teamId));
tinyDb.putBoolean("teamActionFlag", false);
}
}
private void fetchDataAsync(String instanceUrl, String instanceToken, int teamId) {
private void fetchDataAsync(String instanceToken, int teamId) {
TeamMembersByOrgViewModel teamMembersModel = new ViewModelProvider(this).get(TeamMembersByOrgViewModel.class);
teamMembersModel.getMembersByOrgList(instanceUrl, instanceToken, teamId, ctx).observe(this, teamMembersListMain -> {
teamMembersModel.getMembersByOrgList(instanceToken, teamId, ctx).observe(this, teamMembersListMain -> {
adapter = new TeamMembersByOrgAdapter(ctx, teamMembersListMain);
if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter);
noDataMembers.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mGridView.setAdapter(adapter);
noDataMembers.setVisibility(View.VISIBLE);
@ -119,7 +112,6 @@ public class OrganizationTeamMembersActivity extends BaseActivity implements Bot
progressBar.setVisibility(View.GONE);
});
}
@Override
@ -128,7 +120,6 @@ public class OrganizationTeamMembersActivity extends BaseActivity implements Bot
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
return true;
}
@Override
@ -136,31 +127,32 @@ public class OrganizationTeamMembersActivity extends BaseActivity implements Bot
int id = item.getItemId();
switch(id) {
case android.R.id.home:
finish();
return true;
case R.id.genericMenu:
BottomSheetOrganizationTeamsFragment bottomSheet = new BottomSheetOrganizationTeamsFragment();
bottomSheet.show(getSupportFragmentManager(), "orgTeamsBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
if(id == android.R.id.home) {
finish();
return true;
}
else if(id == R.id.genericMenu) {
BottomSheetOrganizationTeamsFragment bottomSheet = new BottomSheetOrganizationTeamsFragment();
bottomSheet.show(getSupportFragmentManager(), "orgTeamsBottomSheet");
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
@Override
public void onButtonClicked(String text) {
TinyDB tinyDb = new TinyDB(appCtx);
if("newMember".equals(text)) {
Intent intent = new Intent(OrganizationTeamMembersActivity.this, AddNewTeamMemberActivity.class);
intent.putExtra("teamId", teamId);
startActivity(intent);
}
}
private void initCloseListener() {

View File

@ -0,0 +1,242 @@
package org.mian.gitnex.activities;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BottomSheetUserProfileFragment;
import org.mian.gitnex.fragments.profile.DetailFragment;
import org.mian.gitnex.fragments.profile.FollowersFragment;
import org.mian.gitnex.fragments.profile.FollowingFragment;
import org.mian.gitnex.fragments.profile.OrganizationsFragment;
import org.mian.gitnex.fragments.profile.RepositoriesFragment;
import org.mian.gitnex.fragments.profile.StarredRepositoriesFragment;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class ProfileActivity extends BaseActivity implements BottomSheetUserProfileFragment.BottomSheetListener {
private String username;
private boolean following;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
Intent profileIntent = getIntent();
Typeface myTypeface;
Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = findViewById(R.id.toolbarTitle);
if(profileIntent.getStringExtra("username") != null && !Objects.equals(profileIntent.getStringExtra("username"), "")) {
username = profileIntent.getStringExtra("username");
}
else {
Toasty.warning(ctx, ctx.getResources().getString(R.string.userInvalidUserName));
finish();
}
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(username);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ViewPager2 viewPager = findViewById(R.id.profileContainer);
viewPager.setOffscreenPageLimit(1);
TabLayout tabLayout = findViewById(R.id.tabs);
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
break;
}
toolbarTitle.setTypeface(myTypeface);
toolbarTitle.setText(username);
viewPager.setAdapter(new ViewPagerAdapter(this));
String[] tabTitles = {ctx.getResources().getString(R.string.tabTextInfo), ctx.getResources().getString(R.string.navRepos), ctx.getResources().getString(R.string.navStarredRepos), ctx.getResources().getString(R.string.navOrg), ctx.getResources().getString(R.string.profileTabFollowers), ctx.getResources().getString(R.string.profileTabFollowing)};
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> tab.setText(tabTitles[position])).attach();
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);
}
}
if(!username.equals(tinyDB.getString("userLogin"))) {
checkFollowStatus();
}
}
}
@Override
public void onButtonClicked(String text) {
if(text.equals("follow")) {
followUnfollow();
}
}
private void checkFollowStatus() {
RetrofitClient.getApiInterface(this).checkFollowing(Authorization.get(this), username).enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull Response<JsonElement> response) {
if(response.code() == 204) {
following = true;
}
else if(response.code() == 404) {
following = false;
}
else {
following = false;
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
following = false;
}
});
}
private void followUnfollow() {
Call<JsonElement> call;
if (following) {
call = RetrofitClient.getApiInterface(this).unfollowUser(Authorization.get(this), username);
}
else {
call = RetrofitClient.getApiInterface(this).followUser(Authorization.get(this), username);
}
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull Response<JsonElement> response) {
if (response.isSuccessful()) {
following = !following;
if (following) {
Toasty.success(ProfileActivity.this, String.format(getString(R.string.nowFollowUser), username));
}
else {
Toasty.success(ProfileActivity.this, String.format(getString(R.string.unfollowedUser), username));
}
} else {
if (following) {
Toasty.error(ProfileActivity.this, getString(R.string.unfollowingFailed));
}
else {
Toasty.error(ProfileActivity.this, getString(R.string.followingFailed));
}
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
if (following) {
Toasty.error(ProfileActivity.this, getString(R.string.unfollowingFailed));
}
else {
Toasty.error(ProfileActivity.this, getString(R.string.followingFailed));
}
}
});
}
public class ViewPagerAdapter extends FragmentStateAdapter {
public ViewPagerAdapter(@NonNull FragmentActivity fa) { super(fa); }
@NonNull
@Override
public Fragment createFragment(int position) {
switch(position) {
case 0: // detail
return DetailFragment.newInstance(username);
case 1: // repos
return RepositoriesFragment.newInstance(username);
case 2: // starred repos
return StarredRepositoriesFragment.newInstance(username);
case 3: // organizations
return OrganizationsFragment.newInstance(username);
case 4: // followers
return FollowersFragment.newInstance(username);
case 5: // following
return FollowingFragment.newInstance(username);
}
return null;
}
@Override
public int getItemCount() {
return 6;
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home) {
finish();
return true;
}
else if(id == R.id.genericMenu) {
new BottomSheetUserProfileFragment(following).show(getSupportFragmentManager(), "userProfileBottomSheet");
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if(!username.equals(tinyDB.getString("userLogin"))) {
getMenuInflater().inflate(R.menu.generic_nav_dotted_menu, menu);
}
return super.onCreateOptionsMenu(menu);
}
}

View File

@ -1,354 +0,0 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.IssueActions;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Issues;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class ReplyToIssueActivity extends BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private TextView draftSaved;
private EditText addComment;
private Button replyButton;
private String TAG = StaticGlobalVariables.replyToIssueActivity;
private long draftIdOnCreate;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_reply_to_issue;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx);
draftSaved = findViewById(R.id.draftSaved);
addComment = findViewById(R.id.addComment);
addComment.setShowSoftInputOnFocus(true);
closeActivity = findViewById(R.id.close);
TextView toolbar_title = findViewById(R.id.toolbar_title);
addComment.requestFocus();
assert imm != null;
imm.showSoftInput(addComment, InputMethodManager.SHOW_IMPLICIT);
if(!tinyDb.getString("issueTitle").isEmpty()) {
toolbar_title.setText(tinyDb.getString("issueTitle"));
}
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(getIntent().getStringExtra("draftId") != null) {
draftIdOnCreate = Long.parseLong(Objects.requireNonNull(getIntent().getStringExtra("draftId")));
}
else {
if(getIntent().getStringExtra("commentBody") != null) {
draftIdOnCreate = returnDraftId(getIntent().getStringExtra("commentBody"));
}
else {
draftIdOnCreate = returnDraftId("");
}
}
replyButton = findViewById(R.id.replyButton);
if(getIntent().getStringExtra("commentBody") != null) {
addComment.setText(getIntent().getStringExtra("commentBody"));
if(getIntent().getBooleanExtra("cursorToEnd", false)) {
addComment.setSelection(addComment.length());
}
}
if(getIntent().getStringExtra("draftTitle") != null) {
toolbar_title.setText(getIntent().getStringExtra("draftTitle"));
}
if(getIntent().getStringExtra("commentAction") != null && Objects.equals(getIntent().getStringExtra("commentAction"), "edit") && !Objects.equals(getIntent().getStringExtra("commentId"), "new")) {
final String commentId = getIntent().getStringExtra("commentId");
toolbar_title.setText(getResources().getString(R.string.editCommentTitle));
replyButton.setText(getResources().getString(R.string.editCommentButtonText));
addComment.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
saveDraft(addComment.getText().toString(), commentId, draftIdOnCreate);
draftSaved.setVisibility(View.VISIBLE);
}
});
replyButton.setOnClickListener(v -> {
disableProcessButton();
assert commentId != null;
IssueActions.editIssueComment(ctx, Integer.parseInt(commentId), addComment.getText().toString(), draftIdOnCreate);
});
return;
}
addComment.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
saveDraft(addComment.getText().toString(), "new", draftIdOnCreate);
draftSaved.setVisibility(View.VISIBLE);
}
});
if(!connToInternet) {
disableProcessButton();
}
else {
replyButton.setOnClickListener(replyToIssue);
}
}
private void saveDraft(String draftText, String commentId, long draftIdOnCreate) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
int repositoryId = (int) tinyDb.getLong("repositoryId", 0);
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
int issueNumber = Integer.parseInt(tinyDb.getString("issueNumber"));
DraftsApi draftsApi = new DraftsApi(appCtx);
if(draftIdOnCreate == 0) {
draftsApi.insertDraft(repositoryId, currentActiveAccountId, issueNumber, draftText, StaticGlobalVariables.draftTypeComment, commentId);
}
else {
DraftsApi.updateDraft(draftText, (int) draftIdOnCreate, commentId); //updateDraftByIssueIdAsyncTask(draftText, issueNumber, repositoryId, commentId);
}
}
private long returnDraftId(String draftText) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
int repositoryId = (int) tinyDb.getLong("repositoryId", 0);
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
int issueNumber = Integer.parseInt(tinyDb.getString("issueNumber"));
DraftsApi draftsApi = new DraftsApi(appCtx);
return draftsApi.insertDraft(repositoryId, currentActiveAccountId, issueNumber, draftText, StaticGlobalVariables.draftTypeComment, "");
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private View.OnClickListener replyToIssue = v -> processNewCommentReply();
private void processNewCommentReply() {
String newReplyDT = addComment.getText().toString();
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newReplyDT.equals("")) {
Toasty.error(ctx, getString(R.string.commentEmptyError));
}
else {
disableProcessButton();
replyComment(newReplyDT);
}
}
private void replyComment(String newReplyDT) {
final TinyDB tinyDb = new TinyDB(appCtx);
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 issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
Issues issueComment = new Issues(newReplyDT);
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.replyCommentToIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueComment);
call.enqueue(new Callback<Issues>() {
@Override
public void onResponse(@NonNull Call<Issues> call, @NonNull retrofit2.Response<Issues> response) {
if(response.code() == 201) {
Toasty.success(ctx, getString(R.string.commentSuccess));
tinyDb.putBoolean("commentPosted", true);
tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("resumePullRequests", true);
// delete draft comment
if(tinyDb.getBoolean("draftsCommentsDeletionEnabled")) {
DraftsApi draftsApi = new DraftsApi(appCtx);
draftsApi.deleteSingleDraft((int) draftIdOnCreate);
}
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 {
enableProcessButton();
Toasty.error(ctx, getString(R.string.commentError));
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
enableProcessButton();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.reply_to_issue, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.replyToIssueMenu:
Intent fragmentIntent = new Intent(ReplyToIssueActivity.this, MainActivity.class);
fragmentIntent.putExtra("launchFragment", "drafts");
ReplyToIssueActivity.this.startActivity(fragmentIntent);
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
private void disableProcessButton() {
replyButton.setEnabled(false);
}
private void enableProcessButton() {
replyButton.setEnabled(true);
}
}

View File

@ -1,10 +1,10 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Typeface;
@ -17,6 +17,7 @@ import android.view.MenuInflater;
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.app.AlertDialog;
@ -27,6 +28,10 @@ import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import com.google.gson.JsonElement;
import org.gitnex.tea4j.models.Branches;
import org.gitnex.tea4j.models.Milestones;
import org.gitnex.tea4j.models.UserRepositories;
import org.gitnex.tea4j.models.WatchInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BottomSheetIssuesFilterFragment;
@ -42,12 +47,8 @@ import org.mian.gitnex.fragments.PullRequestsFragment;
import org.mian.gitnex.fragments.ReleasesFragment;
import org.mian.gitnex.fragments.RepoInfoFragment;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@ -70,15 +71,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
private FragmentRefreshListenerPr fragmentRefreshListenerPr;
private FragmentRefreshListenerMilestone fragmentRefreshListenerMilestone;
private FragmentRefreshListenerFiles fragmentRefreshListenerFiles;
private final Context ctx = this;
private Context appCtx;
private TinyDB tinyDB;
private String instanceUrl;
private String loginUid;
private String instanceToken;
private FragmentRefreshListenerFilterIssuesByMilestone fragmentRefreshListenerFilterIssuesByMilestone;
private String repositoryOwner;
private String repositoryName;
@ -86,19 +79,12 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
public static ViewPager mViewPager;
private int tabsCount;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_repo_detail;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDB = new TinyDB(appCtx);
setContentView(R.layout.activity_repo_detail);
String[] repoNameParts = tinyDB.getString("repoFullName").split("/");
repositoryOwner = repoNameParts[0];
@ -106,17 +92,21 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
TextView toolbarTitle = findViewById(R.id.toolbar_title);
ImageView repoTypeToolbar = findViewById(R.id.repoTypeToolbar);
if(tinyDB.getString("repoType").equalsIgnoreCase("private")) {
repoTypeToolbar.setVisibility(View.VISIBLE);
}
else {
repoTypeToolbar.setVisibility(View.GONE);
}
toolbarTitle.setText(repositoryName);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repositoryName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
instanceUrl = tinyDB.getString("instanceUrl");
loginUid = tinyDB.getString("loginUid");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
tinyDB.putString("repoIssuesState", "open");
tinyDB.putString("repoPrState", "open");
tinyDB.putString("milestoneState", "open");
@ -126,17 +116,17 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
break;
}
toolbarTitle.setTypeface(myTypeface);
@ -156,6 +146,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
View tabViewChild = vgTab.getChildAt(i);
if(tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(myTypeface);
}
}
@ -172,7 +163,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
tabsCount--;
collaboratorTab.setVisibility(View.GONE);
}
mViewPager = findViewById(R.id.container);
@ -198,7 +188,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
textViewBadgePull.setVisibility(View.GONE);
textViewBadgeRelease.setVisibility(View.GONE);
getRepoInfo(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
getRepoInfo(Authorization.get(ctx), repositoryOwner, repositoryName);
ColorStateList textColor = tabLayout.getTabTextColors();
// Issue count
@ -209,7 +199,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
assert tabOpenIssues != null; // FIXME This should be cleaned up
TextView openIssueTabView = Objects.requireNonNull(tabOpenIssues.getCustomView()).findViewById(R.id.counterBadgeIssueText);
openIssueTabView.setTextColor(textColor);
}
// Pull request count
@ -220,7 +209,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
assert tabOpenPulls != null; // FIXME This should be cleaned up
TextView openPullTabView = Objects.requireNonNull(tabOpenPulls.getCustomView()).findViewById(R.id.counterBadgePullText);
openPullTabView.setTextColor(textColor);
}
// Release count
@ -233,7 +221,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
assert tabOpenRelease != null; // FIXME This should be cleaned up
TextView openReleaseTabView = Objects.requireNonNull(tabOpenRelease.getCustomView()).findViewById(R.id.counterBadgeReleaseText);
openReleaseTabView.setTextColor(textColor);
}
}
}
@ -247,19 +234,89 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
mainIntent.removeExtra("goToSection");
mainIntent.removeExtra("goToSectionType");
if(goToSectionType.equals("issue")) {
RepoDetailActivity.mViewPager.setCurrentItem(2);
}
else if(goToSectionType.equals("pull")) {
RepoDetailActivity.mViewPager.setCurrentItem(3);
switch(goToSectionType) {
case "branchesList":
RepoDetailActivity.mViewPager.setCurrentItem(1);
chooseBranch();
break;
case "branch":
RepoDetailActivity.mViewPager.setCurrentItem(1);
String selectedBranch = mainIntent.getStringExtra("selectedBranch");
tinyDB.putString("repoBranch", selectedBranch);
if(getFragmentRefreshListenerFiles() != null) {
getFragmentRefreshListenerFiles().onRefresh(selectedBranch);
}
break;
case "file":
RepoDetailActivity.mViewPager.setCurrentItem(1);
String branch1 = mainIntent.getStringExtra("branch");
tinyDB.putString("repoBranch", branch1);
if(getFragmentRefreshListenerFiles() != null) {
getFragmentRefreshListenerFiles().onRefresh(branch1);
}
Intent intent = new Intent(ctx, FileViewActivity.class);
intent.putExtra("file", mainIntent.getSerializableExtra("file"));
startActivity(intent);
break;
case "dir":
RepoDetailActivity.mViewPager.setCurrentItem(1);
String branch2 = mainIntent.getStringExtra("branch");
tinyDB.putString("repoBranch", branch2);
if(getFragmentRefreshListenerFiles() != null) {
getFragmentRefreshListenerFiles().onRefresh(branch2);
}
//((SectionsPagerAdapter) Objects.requireNonNull(RepoDetailActivity.mViewPager.getAdapter())).getItem(1);
break;
case "commitsList":
RepoDetailActivity.mViewPager.setCurrentItem(1);
String branch = mainIntent.getStringExtra("branchName");
tinyDB.putString("repoBranch", branch);
if(getFragmentRefreshListenerFiles() != null) {
getFragmentRefreshListenerFiles().onRefresh(branch);
}
Intent intent1 = new Intent(ctx, CommitsActivity.class);
intent1.putExtra("branchName", branch);
ctx.startActivity(intent1);
break;
case "issue":
RepoDetailActivity.mViewPager.setCurrentItem(2);
break;
case "issueNew":
RepoDetailActivity.mViewPager.setCurrentItem(2);
startActivity(new Intent(RepoDetailActivity.this, CreateIssueActivity.class));
break;
case "pull":
RepoDetailActivity.mViewPager.setCurrentItem(3);
break;
case "pullNew":
RepoDetailActivity.mViewPager.setCurrentItem(3);
startActivity(new Intent(RepoDetailActivity.this, CreatePullRequestActivity.class));
break;
case "releases":
RepoDetailActivity.mViewPager.setCurrentItem(4);
break;
case "newRelease":
RepoDetailActivity.mViewPager.setCurrentItem(4);
startActivity(new Intent(RepoDetailActivity.this, CreateReleaseActivity.class));
break;
case "milestones":
RepoDetailActivity.mViewPager.setCurrentItem(5);
break;
case "milestonesNew":
RepoDetailActivity.mViewPager.setCurrentItem(5);
startActivity(new Intent(RepoDetailActivity.this, CreateMilestoneActivity.class));
break;
case "labels":
RepoDetailActivity.mViewPager.setCurrentItem(6);
break;
case "settings":
startActivity(new Intent(RepoDetailActivity.this, RepositorySettingsActivity.class));
break;
}
}
checkRepositoryStarStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
checkRepositoryWatchStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
checkRepositoryStarStatus(Authorization.get(ctx), repositoryOwner, repositoryName);
checkRepositoryWatchStatus(Authorization.get(ctx), repositoryOwner, repositoryName);
}
@Override
@ -269,9 +326,8 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
if(tinyDB.getBoolean("enableCounterIssueBadge")) {
getRepoInfo(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
getRepoInfo(Authorization.get(ctx), repositoryOwner, repositoryName);
}
}
@Override
@ -280,7 +336,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.repo_dotted_menu, menu);
return true;
}
@Override
@ -288,46 +343,49 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
int id = item.getItemId();
switch(id) {
case android.R.id.home:
finish();
return true;
case R.id.repoMenu:
BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment();
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
return true;
case R.id.filter:
BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment();
filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet");
return true;
case R.id.filterPr:
BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment();
filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet");
return true;
case R.id.filterMilestone:
BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment();
filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet");
return true;
case R.id.switchBranches:
chooseBranch();
return true;
case R.id.branchCommits:
Intent intent = new Intent(ctx, CommitsActivity.class);
intent.putExtra("branchName", tinyDB.getString("repoBranch"));
ctx.startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
if(id == android.R.id.home) {
finish();
return true;
}
else if(id == R.id.repoMenu) {
BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment();
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
return true;
}
else if(id == R.id.filter) {
BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment();
filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet");
return true;
}
else if(id == R.id.filterPr) {
BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment();
filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet");
return true;
}
else if(id == R.id.filterMilestone) {
BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment();
filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet");
return true;
}
else if(id == R.id.switchBranches) {
chooseBranch();
return true;
}
else if(id == R.id.branchCommits) {
Intent intent = new Intent(ctx, CommitsActivity.class);
intent.putExtra("branchName", tinyDB.getString("repoBranch"));
ctx.startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
@ -337,113 +395,187 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
switch(text) {
case "label":
startActivity(new Intent(RepoDetailActivity.this, CreateLabelActivity.class));
break;
case "newIssue":
startActivity(new Intent(RepoDetailActivity.this, CreateIssueActivity.class));
break;
case "newMilestone":
startActivity(new Intent(RepoDetailActivity.this, CreateMilestoneActivity.class));
break;
case "addCollaborator":
startActivity(new Intent(RepoDetailActivity.this, AddCollaboratorToRepositoryActivity.class));
break;
case "chooseBranch":
chooseBranch();
break;
case "createRelease":
startActivity(new Intent(RepoDetailActivity.this, CreateReleaseActivity.class));
break;
case "openWebRepo":
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(tinyDB.getString("repoHtmlUrl")));
startActivity(i);
break;
case "shareRepo":
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, tinyDB.getString("repoHtmlUrl"));
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, tinyDB.getString("repoHtmlUrl"));
startActivity(Intent.createChooser(sharingIntent, tinyDB.getString("repoHtmlUrl")));
break;
case "copyRepoUrl":
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("repoUrl", tinyDB.getString("repoHtmlUrl"));
assert clipboard != null;
clipboard.setPrimaryClip(clip);
Toasty.info(ctx, ctx.getString(R.string.copyIssueUrlToastMsg));
break;
case "newFile":
startActivity(new Intent(RepoDetailActivity.this, CreateFileActivity.class));
break;
case "filterByMilestone":
filterIssuesByMilestone();
break;
case "openIssues":
if(getFragmentRefreshListener() != null) {
getFragmentRefreshListener().onRefresh("open");
}
break;
case "closedIssues":
if(getFragmentRefreshListener() != null) {
getFragmentRefreshListener().onRefresh("closed");
}
break;
case "openPr":
if(getFragmentRefreshListenerPr() != null) {
getFragmentRefreshListenerPr().onRefresh("open");
}
break;
case "closedPr":
if(getFragmentRefreshListenerPr() != null) {
getFragmentRefreshListenerPr().onRefresh("closed");
}
break;
case "openMilestone":
if(getFragmentRefreshListenerMilestone() != null) {
getFragmentRefreshListenerMilestone().onRefresh("open");
}
break;
case "closedMilestone":
if(getFragmentRefreshListenerMilestone() != null) {
getFragmentRefreshListenerMilestone().onRefresh("closed");
}
break;
case "repoSettings":
startActivity(new Intent(RepoDetailActivity.this, RepositorySettingsActivity.class));
break;
case "newPullRequest":
startActivity(new Intent(RepoDetailActivity.this, CreatePullRequestActivity.class));
break;
}
}
private void filterIssuesByMilestone() {
Dialog progressDialog = new Dialog(this);
progressDialog.setContentView(R.layout.custom_progress_loader);
progressDialog.show();
Call<List<Milestones>> call = RetrofitClient
.getApiInterface(ctx)
.getMilestones(Authorization.get(ctx), repositoryOwner, repositoryName, 1, 50, "open");
call.enqueue(new Callback<List<Milestones>>() {
@Override
public void onResponse(@NonNull Call<List<Milestones>> call, @NonNull Response<List<Milestones>> response) {
progressDialog.hide();
if(response.code() == 200) {
Milestones milestones;
List<String> milestonesList = new ArrayList<>();
int selectedMilestone = 0;
assert response.body() != null;
milestonesList.add("All");
for(int i = 0; i < response.body().size(); i++) {
milestones = response.body().get(i);
milestonesList.add(milestones.getTitle());
}
for(int j = 0; j < milestonesList.size(); j++) {
if(tinyDB.getString("issueMilestoneFilterId").equals(milestonesList.get(j))) {
selectedMilestone = j;
}
}
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx);
pBuilder.setTitle(R.string.selectMilestone);
pBuilder.setSingleChoiceItems(milestonesList.toArray(new String[0]), selectedMilestone, (dialogInterface, i) -> {
tinyDB.putString("issueMilestoneFilterId", milestonesList.get(i));
if(getFragmentRefreshListenerFilterIssuesByMilestone() != null) {
getFragmentRefreshListenerFilterIssuesByMilestone().onRefresh(milestonesList.get(i));
}
dialogInterface.dismiss();
});
pBuilder.setNeutralButton(R.string.cancelButton, null);
pBuilder.create().show();
}
}
@Override
public void onFailure(@NonNull Call<List<Milestones>> call, @NonNull Throwable t) {
progressDialog.hide();
Log.e("onFailure", t.toString());
}
});
}
private void chooseBranch() {
Call<List<Branches>> call = RetrofitClient.getInstance(instanceUrl, ctx)
.getApiInterface()
.getBranches(instanceToken, repositoryOwner, repositoryName);
Dialog progressDialog = new Dialog(this);
progressDialog.setContentView(R.layout.custom_progress_loader);
progressDialog.show();
Call<List<Branches>> call = RetrofitClient
.getApiInterface(ctx)
.getBranches(Authorization.get(ctx), repositoryOwner, repositoryName);
call.enqueue(new Callback<List<Branches>>() {
@Override
public void onResponse(@NonNull Call<List<Branches>> call, @NonNull Response<List<Branches>> response) {
progressDialog.hide();
if(response.code() == 200) {
List<String> branchesList = new ArrayList<>();
@ -456,7 +588,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
branchesList.add(branches.getName());
if(tinyDB.getString("repoBranch").equals(branches.getName())) {
selectedBranch = i;
}
}
@ -464,33 +595,27 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx);
pBuilder.setTitle(R.string.pageTitleChooseBranch);
pBuilder.setSingleChoiceItems(branchesList.toArray(new String[0]), selectedBranch, new DialogInterface.OnClickListener() {
pBuilder.setSingleChoiceItems(branchesList.toArray(new String[0]), selectedBranch, (dialogInterface, i) -> {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
tinyDB.putString("repoBranch", branchesList.get(i));
tinyDB.putString("repoBranch", branchesList.get(i));
if(getFragmentRefreshListenerFiles() != null) {
getFragmentRefreshListenerFiles().onRefresh(branchesList.get(i));
}
dialogInterface.dismiss();
if(getFragmentRefreshListenerFiles() != null) {
getFragmentRefreshListenerFiles().onRefresh(branchesList.get(i));
}
dialogInterface.dismiss();
});
pBuilder.setNeutralButton(R.string.cancelButton, null);
pBuilder.create().show();
}
}
@Override
public void onFailure(@NonNull Call<List<Branches>> call, @NonNull Throwable t) {
progressDialog.hide();
Log.e("onFailure", t.toString());
}
});
}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
@ -509,37 +634,36 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
switch(position) {
case 0: // Repository details
return RepoInfoFragment.newInstance(repositoryOwner, repositoryName);
case 1: // Files
return FilesFragment.newInstance(repositoryOwner, repositoryName, tinyDB.getString("repoBranch"));
return FilesFragment.newInstance(repositoryOwner, repositoryName, tinyDB.getString("repoBranch"));
case 2: // Issues
fragment = new IssuesFragment();
break;
case 3: // Pull requests
fragment = new PullRequestsFragment();
break;
case 4: // Releases
return ReleasesFragment.newInstance(repositoryOwner, repositoryName);
return ReleasesFragment.newInstance(repositoryOwner, repositoryName);
case 5: // Milestones
fragment = new MilestonesFragment();
break;
case 6: // Labels
return LabelsFragment.newInstance(repositoryOwner, repositoryName);
case 7: // Collaborators
return CollaboratorsFragment.newInstance(repositoryOwner, repositoryName);
return CollaboratorsFragment.newInstance(repositoryOwner, repositoryName);
}
assert fragment != null;
return fragment;
}
@Override
@ -547,12 +671,11 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
return tabsCount;
}
}
private void getRepoInfo(String instanceUrl, String token, final String owner, String repo) {
private void getRepoInfo(String token, final String owner, String repo) {
Call<UserRepositories> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserRepository(token, owner, repo);
Call<UserRepositories> call = RetrofitClient.getApiInterface(ctx).getUserRepository(token, owner, repo);
call.enqueue(new Callback<UserRepositories>() {
@Override
@ -563,6 +686,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
if(response.code() == 200) {
if(tinyDB.getBoolean("enableCounterBadges")) {
assert repoInfo != null;
if(repoInfo.getOpen_issues_count() != null) {
@ -589,7 +713,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
Log.e("onFailure", String.valueOf(response.code()));
}
}
@Override
@ -602,16 +725,15 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
}
private void checkRepositoryStarStatus(String instanceUrl, String instanceToken, final String owner, String repo) {
private void checkRepositoryStarStatus(String instanceToken, final String owner, String repo) {
Call<JsonElement> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkRepoStarStatus(instanceToken, owner, repo);
Call<JsonElement> call = RetrofitClient.getApiInterface(ctx).checkRepoStarStatus(instanceToken, owner, repo);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
tinyDB.putInt("repositoryStarStatus", response.code());
}
@Override
@ -623,11 +745,11 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
}
private void checkRepositoryWatchStatus(String instanceUrl, String instanceToken, final String owner, String repo) {
private void checkRepositoryWatchStatus(String instanceToken, final String owner, String repo) {
Call<WatchInfo> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkRepoWatchStatus(instanceToken, owner, repo);
call = RetrofitClient.getApiInterface(ctx).checkRepoWatchStatus(instanceToken, owner, repo);
call.enqueue(new Callback<WatchInfo>() {
@Override
@ -638,15 +760,14 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
assert response.body() != null;
if(response.body().getSubscribed()) {
tinyDB.putBoolean("repositoryWatchStatus", true);
}
}
else {
tinyDB.putBoolean("repositoryWatchStatus", false);
}
}
@Override
@ -658,6 +779,13 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
}
// Issues milestone filter interface
public FragmentRefreshListenerFilterIssuesByMilestone getFragmentRefreshListenerFilterIssuesByMilestone() { return fragmentRefreshListenerFilterIssuesByMilestone; }
public void setFragmentRefreshListenerFilterIssuesByMilestone(FragmentRefreshListenerFilterIssuesByMilestone fragmentRefreshListener) { this.fragmentRefreshListenerFilterIssuesByMilestone = fragmentRefreshListener; }
public interface FragmentRefreshListenerFilterIssuesByMilestone { void onRefresh(String text); }
// Issues interface
public FragmentRefreshListener getFragmentRefreshListener() { return fragmentRefreshListener; }

View File

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@ -22,14 +21,15 @@ import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.gitnex.tea4j.models.UserRepositories;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoForksAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityRepoForksBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.UserRepositories;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
@ -42,13 +42,11 @@ import retrofit2.Response;
public class RepoForksActivity extends BaseActivity {
final Context ctx = this;
private Context appCtx;
private View.OnClickListener onClickListener;
private TextView noData;
private ProgressBar progressBar;
private String TAG = "RepositoryForks";
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private final String TAG = "RepositoryForks";
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private int pageSize = 1;
private RecyclerView recyclerView;
@ -56,25 +54,19 @@ public class RepoForksActivity extends BaseActivity {
private RepoForksAdapter adapter;
private ProgressBar progressLoadMore;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_forks;
}
@SuppressLint("DefaultLocale")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
Toolbar toolbar = findViewById(R.id.toolbar);
ActivityRepoForksBinding activityRepoForksBinding = ActivityRepoForksBinding.inflate(getLayoutInflater());
setContentView(activityRepoForksBinding.getRoot());
Toolbar toolbar = activityRepoForksBinding.toolbar;
setSupportActionBar(toolbar);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
TinyDB tinyDb = TinyDB.getInstance(appCtx);
String repoFullNameForForks = getIntent().getStringExtra("repoFullNameForForks");
assert repoFullNameForForks != null;
@ -82,25 +74,26 @@ public class RepoForksActivity extends BaseActivity {
final String repoOwner = parts[0];
final String repoName = parts[1];
TextView toolbar_title = findViewById(R.id.toolbar_title);
TextView toolbar_title = activityRepoForksBinding.toolbarTitle;
toolbar_title.setMovementMethod(new ScrollingMovementMethod());
toolbar_title.setText(String.format("%s : %s", ctx.getResources().getString(R.string.infoTabRepoForksCount), repoName));
ImageView closeActivity = findViewById(R.id.close);
noData = findViewById(R.id.noData);
progressLoadMore = findViewById(R.id.progressLoadMore);
progressBar = findViewById(R.id.progress_bar);
SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh);
ImageView closeActivity = activityRepoForksBinding.close;
noData = activityRepoForksBinding.noData;
progressLoadMore = activityRepoForksBinding.progressLoadMore;
progressBar = activityRepoForksBinding.progressBar;
SwipeRefreshLayout swipeRefresh = activityRepoForksBinding.pullToRefresh;
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
// if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances)
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
resultLimit = Constants.resultLimitNewGiteaInstances;
}
recyclerView = findViewById(R.id.recyclerView);
recyclerView = activityRepoForksBinding.recyclerView;
forksList = new ArrayList<>();
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
@ -110,7 +103,7 @@ public class RepoForksActivity extends BaseActivity {
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
loadInitial(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, pageSize, resultLimit);
loadInitial(Authorization.get(ctx), repoOwner, repoName, pageSize, resultLimit);
adapter.notifyDataChanged();
}, 200));
@ -121,25 +114,21 @@ public class RepoForksActivity extends BaseActivity {
if(forksList.size() == resultLimit || pageSize == resultLimit) {
int page = (forksList.size() + resultLimit) / resultLimit;
loadMore(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, page, resultLimit);
loadMore(Authorization.get(ctx), repoOwner, repoName, page, resultLimit);
}
}));
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
recyclerView.setAdapter(adapter);
loadInitial(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, pageSize, resultLimit);
loadInitial(Authorization.get(ctx), repoOwner, repoName, pageSize, resultLimit);
}
private void loadInitial(String instanceUrl, String instanceToken, String repoOwner, String repoName, int pageSize, int resultLimit) {
private void loadInitial(String instanceToken, String repoOwner, String repoName, int pageSize, int resultLimit) {
Call<List<UserRepositories>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.getRepositoryForks(instanceToken, repoOwner, repoName, pageSize, resultLimit);
call.enqueue(new Callback<List<UserRepositories>>() {
@ -150,29 +139,27 @@ public class RepoForksActivity extends BaseActivity {
if(response.isSuccessful()) {
assert response.body() != null;
if(response.body().size() > 0) {
forksList.clear();
forksList.addAll(response.body());
adapter.notifyDataChanged();
noData.setVisibility(View.GONE);
}
else {
forksList.clear();
adapter.notifyDataChanged();
noData.setVisibility(View.VISIBLE);
}
progressBar.setVisibility(View.GONE);
}
else {
Log.e(TAG, String.valueOf(response.code()));
}
}
@Override
@ -180,18 +167,16 @@ public class RepoForksActivity extends BaseActivity {
Log.e(TAG, t.toString());
}
});
}
private void loadMore(String instanceUrl, String instanceToken, String repoOwner, String repoName, int page, int resultLimit) {
private void loadMore(String instanceToken, String repoOwner, String repoName, int page, int resultLimit) {
progressLoadMore.setVisibility(View.VISIBLE);
Call<List<UserRepositories>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.getRepositoryForks(instanceToken, repoOwner, repoName, page, resultLimit);
call.enqueue(new Callback<List<UserRepositories>>() {
@ -205,37 +190,31 @@ public class RepoForksActivity extends BaseActivity {
forksList.remove(forksList.size() - 1);
List<UserRepositories> result = response.body();
assert result != null;
if(result.size() > 0) {
pageSize = result.size();
forksList.addAll(result);
}
else {
adapter.setMoreDataAvailable(false);
}
adapter.notifyDataChanged();
progressLoadMore.setVisibility(View.GONE);
}
else {
Log.e(TAG, String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<UserRepositories>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
@ -270,7 +249,6 @@ public class RepoForksActivity extends BaseActivity {
});
return super.onCreateOptionsMenu(menu);
}
private void filter(String text) {
@ -278,7 +256,9 @@ public class RepoForksActivity extends BaseActivity {
List<UserRepositories> arr = new ArrayList<>();
for(UserRepositories d : forksList) {
if(d.getName().toLowerCase().contains(text) || d.getDescription().toLowerCase().contains(text)) {
arr.add(d);
}
}
@ -289,6 +269,7 @@ public class RepoForksActivity extends BaseActivity {
private void initCloseListener() {
onClickListener = view -> {
getIntent().removeExtra("repoFullNameForForks");
finish();
};

View File

@ -1,22 +1,17 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoStargazersAdapter;
import org.mian.gitnex.databinding.ActivityRepoStargazersBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.viewmodels.RepoStargazersViewModel;
import java.util.List;
/**
* Author M M Arif
@ -30,30 +25,19 @@ public class RepoStargazersActivity extends BaseActivity {
private GridView mGridView;
private ProgressBar mProgressBar;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repo_stargazers;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
super.onCreate(savedInstanceState);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ActivityRepoStargazersBinding activityRepoStargazersBinding = ActivityRepoStargazersBinding.inflate(getLayoutInflater());
setContentView(activityRepoStargazersBinding.getRoot());
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);
ImageView closeActivity = activityRepoStargazersBinding.close;
TextView toolbarTitle = activityRepoStargazersBinding.toolbarTitle;
noDataStargazers = activityRepoStargazersBinding.noDataStargazers;
mGridView = activityRepoStargazersBinding.gridView;
mProgressBar = activityRepoStargazersBinding.progressBar;
String repoFullNameForStars = getIntent().getStringExtra("repoFullNameForStars");
String[] parts = repoFullNameForStars.split("/");
@ -65,29 +49,30 @@ public class RepoStargazersActivity extends BaseActivity {
toolbarTitle.setText(R.string.repoStargazersInMenu);
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
fetchDataAsync(Authorization.get(ctx), repoOwner, repoName);
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String repoOwner, String repoName) {
private void fetchDataAsync(String instanceToken, String repoOwner, String repoName) {
RepoStargazersViewModel repoStargazersModel = new ViewModelProvider(this).get(RepoStargazersViewModel.class);
repoStargazersModel.getRepoStargazers(instanceUrl, instanceToken, repoOwner, repoName, ctx).observe(this, new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> stargazersListMain) {
adapter = new RepoStargazersAdapter(ctx, 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);
repoStargazersModel.getRepoStargazers(instanceToken, repoOwner, repoName, ctx).observe(this, stargazersListMain -> {
adapter = new RepoStargazersAdapter(ctx, 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);
});
}

View File

@ -1,22 +1,17 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoWatchersAdapter;
import org.mian.gitnex.databinding.ActivityRepoWatchersBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.viewmodels.RepoWatchersViewModel;
import java.util.List;
/**
* Author M M Arif
@ -30,30 +25,19 @@ public class RepoWatchersActivity extends BaseActivity {
private GridView mGridView;
private ProgressBar mProgressBar;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repo_watchers;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ActivityRepoWatchersBinding activityRepoWatchersBinding = ActivityRepoWatchersBinding.inflate(getLayoutInflater());
setContentView(activityRepoWatchersBinding.getRoot());
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);
ImageView closeActivity = activityRepoWatchersBinding.close;
TextView toolbarTitle = activityRepoWatchersBinding.toolbarTitle;
noDataWatchers = activityRepoWatchersBinding.noDataWatchers;
mGridView = activityRepoWatchersBinding.gridView;
mProgressBar = activityRepoWatchersBinding.progressBar;
String repoFullNameForWatchers = getIntent().getStringExtra("repoFullNameForWatchers");
String[] parts = repoFullNameForWatchers.split("/");
@ -65,29 +49,30 @@ public class RepoWatchersActivity extends BaseActivity {
toolbarTitle.setText(R.string.repoWatchersInMenu);
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
fetchDataAsync(Authorization.get(ctx), repoOwner, repoName);
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String repoOwner, String repoName) {
private void fetchDataAsync(String instanceToken, String repoOwner, String repoName) {
RepoWatchersViewModel repoWatchersModel = new ViewModelProvider(this).get(RepoWatchersViewModel.class);
repoWatchersModel.getRepoWatchers(instanceUrl, instanceToken, repoOwner, repoName, ctx).observe(this, new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> watchersListMain) {
adapter = new RepoWatchersAdapter(ctx, 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);
repoWatchersModel.getRepoWatchers(instanceToken, repoOwner, repoName, ctx).observe(this, watchersListMain -> {
adapter = new RepoWatchersAdapter(ctx, 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);
});
}

View File

@ -1,7 +1,6 @@
package org.mian.gitnex.activities;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
@ -11,18 +10,18 @@ import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.gitnex.tea4j.models.RepositoryTransfer;
import org.gitnex.tea4j.models.UserRepositories;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.databinding.ActivityRepositorySettingsBinding;
import org.mian.gitnex.databinding.CustomRepositoryDeleteDialogBinding;
import org.mian.gitnex.databinding.CustomRepositoryEditPropertiesDialogBinding;
import org.mian.gitnex.databinding.CustomRepositoryTransferDialogBinding;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.RepositoryTransfer;
import org.mian.gitnex.models.UserRepositories;
import retrofit2.Call;
import retrofit2.Callback;
@ -40,40 +39,27 @@ public class RepositorySettingsActivity extends BaseActivity {
private Dialog dialogDeleteRepository;
private Dialog dialogTransferRepository;
private View.OnClickListener onClickListener;
private Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
private String instanceUrl;
private String loginUid;
private String instanceToken;
private String repositoryOwner;
private String repositoryName;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repository_settings;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
viewBinding = ActivityRepositorySettingsBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
setContentView(viewBinding.getRoot());
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
loginUid = tinyDB.getString("loginUid");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repositoryOwner = parts[0];
repositoryName = parts[1];
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
@ -81,23 +67,16 @@ public class RepositorySettingsActivity extends BaseActivity {
closeActivity.setOnClickListener(onClickListener);
// require gitea 1.12 or higher
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
viewBinding.transferOwnerFrame.setVisibility(View.VISIBLE);
}
viewBinding.editProperties.setOnClickListener(editProperties -> {
showRepositoryProperties();
});
viewBinding.editProperties.setOnClickListener(editProperties -> showRepositoryProperties());
viewBinding.deleteRepository.setOnClickListener(deleteRepository -> {
showDeleteRepository();
});
viewBinding.transferOwnerFrame.setOnClickListener(transferRepositoryOwnership -> {
showTransferRepository();
});
viewBinding.deleteRepository.setOnClickListener(deleteRepository -> showDeleteRepository());
viewBinding.transferOwnerFrame.setOnClickListener(transferRepositoryOwnership -> showTransferRepository());
}
private void showTransferRepository() {
@ -114,9 +93,7 @@ public class RepositorySettingsActivity extends BaseActivity {
View view = transferRepoBinding.getRoot();
dialogTransferRepository.setContentView(view);
transferRepoBinding.cancel.setOnClickListener(editProperties -> {
dialogTransferRepository.dismiss();
});
transferRepoBinding.cancel.setOnClickListener(editProperties -> dialogTransferRepository.dismiss());
transferRepoBinding.transfer.setOnClickListener(deleteRepo -> {
@ -137,6 +114,7 @@ public class RepositorySettingsActivity extends BaseActivity {
}
});
dialogTransferRepository.setCancelable(false);
dialogTransferRepository.show();
}
@ -145,8 +123,7 @@ public class RepositorySettingsActivity extends BaseActivity {
RepositoryTransfer repositoryTransfer = new RepositoryTransfer(newOwner);
Call<JsonElement> transferCall = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.transferRepository(instanceToken, repositoryOwner, repositoryName, repositoryTransfer);
transferCall.enqueue(new Callback<JsonElement>() {
@ -163,7 +140,7 @@ public class RepositorySettingsActivity extends BaseActivity {
Toasty.success(ctx, getString(R.string.repoTransferSuccess));
finish();
RepositoriesApi.deleteRepository((int) tinyDb.getLong("repositoryId", 0));
BaseApi.getInstance(ctx, RepositoriesApi.class).deleteRepository((int) tinyDB.getLong("repositoryId", 0));
Intent intent = new Intent(RepositorySettingsActivity.this, MainActivity.class);
RepositorySettingsActivity.this.startActivity(intent);
}
@ -197,6 +174,7 @@ public class RepositorySettingsActivity extends BaseActivity {
dialogDeleteRepository = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogDeleteRepository.getWindow() != null) {
dialogDeleteRepository.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
@ -205,9 +183,7 @@ public class RepositorySettingsActivity extends BaseActivity {
View view = deleteRepoBinding.getRoot();
dialogDeleteRepository.setContentView(view);
deleteRepoBinding.cancel.setOnClickListener(editProperties -> {
dialogDeleteRepository.dismiss();
});
deleteRepoBinding.cancel.setOnClickListener(editProperties -> dialogDeleteRepository.dismiss());
deleteRepoBinding.delete.setOnClickListener(deleteRepo -> {
@ -221,14 +197,14 @@ public class RepositorySettingsActivity extends BaseActivity {
}
});
dialogDeleteRepository.setCancelable(false);
dialogDeleteRepository.show();
}
private void deleteRepository() {
Call<JsonElement> deleteCall = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.deleteRepository(instanceToken, repositoryOwner, repositoryName);
deleteCall.enqueue(new Callback<JsonElement>() {
@ -245,7 +221,7 @@ public class RepositorySettingsActivity extends BaseActivity {
Toasty.success(ctx, getString(R.string.repoDeletionSuccess));
finish();
RepositoriesApi.deleteRepository((int) tinyDb.getLong("repositoryId", 0));
BaseApi.getInstance(ctx, RepositoriesApi.class).deleteRepository((int) tinyDB.getLong("repositoryId", 0));
Intent intent = new Intent(RepositorySettingsActivity.this, MainActivity.class);
RepositorySettingsActivity.this.startActivity(intent);
}
@ -273,6 +249,7 @@ public class RepositorySettingsActivity extends BaseActivity {
dialogProp = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogProp.getWindow() != null) {
dialogProp.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
@ -281,13 +258,10 @@ public class RepositorySettingsActivity extends BaseActivity {
View view = propBinding.getRoot();
dialogProp.setContentView(view);
propBinding.cancel.setOnClickListener(editProperties -> {
dialogProp.dismiss();
});
propBinding.cancel.setOnClickListener(editProperties -> dialogProp.dismiss());
Call<UserRepositories> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.getUserRepository(instanceToken, repositoryOwner, repositoryName);
call.enqueue(new Callback<UserRepositories>() {
@ -314,19 +288,24 @@ public class RepositorySettingsActivity extends BaseActivity {
propBinding.repoEnableIssues.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
propBinding.repoEnableTimer.setVisibility(View.VISIBLE);
}
else {
propBinding.repoEnableTimer.setVisibility(View.GONE);
}
});
if(repoInfo.getInternal_tracker() != null) {
propBinding.repoEnableTimer.setChecked(repoInfo.getInternal_tracker().isEnable_time_tracker());
}
else {
propBinding.repoEnableTimer.setVisibility(View.GONE);
}
propBinding.repoEnableWiki.setChecked(repoInfo.isHas_wiki());
propBinding.repoEnablePr.setChecked(repoInfo.isHas_pull_requests());
propBinding.repoEnableMerge.setChecked(repoInfo.isAllow_merge_commits());
@ -358,8 +337,8 @@ public class RepositorySettingsActivity extends BaseActivity {
propBinding.repoEnableMerge.isChecked(), propBinding.repoEnableRebase.isChecked(),
propBinding.repoEnableSquash.isChecked(), propBinding.repoEnableForceMerge.isChecked()));
dialogProp.setCancelable(false);
dialogProp.show();
}
private void saveRepositoryProperties(String repoName, String repoWebsite, String repoDescription,
@ -370,18 +349,20 @@ public class RepositorySettingsActivity extends BaseActivity {
UserRepositories.internalTimeTrackerObject repoPropsTimeTracker = new UserRepositories.internalTimeTrackerObject(repoEnableTimer);
UserRepositories repoProps;
if(!repoEnableIssues) {
repoProps = new UserRepositories(repoName, repoWebsite, repoDescription, repoPrivate, repoAsTemplate, repoEnableIssues, repoEnableWiki, repoEnablePr, repoEnableMerge,
repoEnableRebase, repoEnableSquash, repoEnableForceMerge);
}
else {
repoProps = new UserRepositories(repoName, repoWebsite, repoDescription, repoPrivate, repoAsTemplate, repoEnableIssues, repoEnableWiki, repoEnablePr, repoPropsTimeTracker, repoEnableMerge,
repoEnableRebase, repoEnableSquash, repoEnableForceMerge);
}
Call<UserRepositories> propsCall = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.updateRepositoryProperties(instanceToken, repositoryOwner, repositoryName, repoProps);
propsCall.enqueue(new Callback<UserRepositories>() {
@ -394,8 +375,8 @@ public class RepositorySettingsActivity extends BaseActivity {
if (response.code() == 200) {
tinyDb.putBoolean("hasIssues", repoEnableIssues);
tinyDb.putBoolean("hasPullRequests", repoEnablePr);
tinyDB.putBoolean("hasIssues", repoEnableIssues);
tinyDB.putBoolean("hasPullRequests", repoEnablePr);
dialogProp.dismiss();
Toasty.success(ctx, getString(R.string.repoPropertiesSaveSuccess));
@ -403,10 +384,9 @@ public class RepositorySettingsActivity extends BaseActivity {
if(!repositoryName.equals(repoName)) {
finish();
RepositoriesApi.updateRepositoryOwnerAndName(repositoryOwner, repoName, (int) tinyDb.getLong("repositoryId", 0));
BaseApi.getInstance(ctx, RepositoriesApi.class).updateRepositoryOwnerAndName(repositoryOwner, repoName, (int) tinyDB.getLong("repositoryId", 0));
Intent intent = new Intent(RepositorySettingsActivity.this, MainActivity.class);
RepositorySettingsActivity.this.startActivity(intent);
}
}
else {
@ -415,7 +395,6 @@ public class RepositorySettingsActivity extends BaseActivity {
propBinding.processingRequest.setVisibility(View.GONE);
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override

View File

@ -1,17 +1,21 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.TimePicker;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.switchmaterial.SwitchMaterial;
import org.jetbrains.annotations.NotNull;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsAppearanceBinding;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
/**
* Author M M Arif
@ -19,122 +23,80 @@ import org.mian.gitnex.helpers.Version;
public class SettingsAppearanceActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
private static String[] timeList = {"Pretty", "Normal"};
private static String[] timeList;
private static int timeSelectedChoice = 0;
private static String[] codeBlockList = {"Green - Black", "White - Black", "Grey - Black", "White - Grey", "Dark - White"};
private static int codeBlockSelectedChoice = 0;
private static String[] homeScreenList = {"My Repositories", "Starred Repositories", "Organizations", "Repositories", "Profile", "Explore", "Drafts"};
private static String[] homeScreenListNew = {"My Repositories", "Starred Repositories", "Organizations", "Repositories", "Profile", "Explore", "Drafts", "Notifications"};
private static int homeScreenSelectedChoice = 0;
private static String[] customFontList = {"Roboto", "Manrope", "Source Code Pro"};
private static String[] customFontList;
private static int customFontSelectedChoice = 0;
private static String[] themeList = {"Dark", "Light", "Auto (Light / Dark)", "Retro", "Auto (Retro / Dark)"};
private static String[] themeList;
private static int themeSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_appearance;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
final TinyDB tinyDb = new TinyDB(appCtx);
ActivitySettingsAppearanceBinding activitySettingsAppearanceBinding = ActivitySettingsAppearanceBinding.inflate(getLayoutInflater());
setContentView(activitySettingsAppearanceBinding.getRoot());
ImageView closeActivity = findViewById(R.id.close);
ImageView closeActivity = activitySettingsAppearanceBinding.close;
final TextView tvDateTimeSelected = findViewById(R.id.tvDateTimeSelected); // setter for time
final TextView codeBlockSelected = findViewById(R.id.codeBlockSelected); // setter for code block
final TextView homeScreenSelected = findViewById(R.id.homeScreenSelected); // setter for home screen
final TextView customFontSelected = findViewById(R.id.customFontSelected); // setter for custom font
final TextView themeSelected = findViewById(R.id.themeSelected); // setter for theme
LinearLayout timeFrame = activitySettingsAppearanceBinding.timeFrame;
LinearLayout customFontFrame = activitySettingsAppearanceBinding.customFontFrame;
LinearLayout themeFrame = activitySettingsAppearanceBinding.themeSelectionFrame;
LinearLayout lightTimeFrame = activitySettingsAppearanceBinding.lightThemeTimeSelectionFrame;
LinearLayout darkTimeFrame = activitySettingsAppearanceBinding.darkThemeTimeSelectionFrame;
LinearLayout timeFrame = findViewById(R.id.timeFrame);
LinearLayout codeBlockFrame = findViewById(R.id.codeBlockFrame);
LinearLayout homeScreenFrame = findViewById(R.id.homeScreenFrame);
LinearLayout customFontFrame = findViewById(R.id.customFontFrame);
LinearLayout themeFrame = findViewById(R.id.themeSelectionFrame);
SwitchMaterial counterBadgesSwitch = activitySettingsAppearanceBinding.switchCounterBadge;
Switch counterBadgesSwitch = findViewById(R.id.switchCounterBadge);
timeList = getResources().getStringArray(R.array.timeFormats);
customFontList = getResources().getStringArray(R.array.fonts);
themeList = getResources().getStringArray(R.array.themes);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.3")) {
String lightMinute = String.valueOf(tinyDB.getInt("lightThemeTimeMinute"));
String lightHour = String.valueOf(tinyDB.getInt("lightThemeTimeHour"));
if(lightMinute.length() == 1) lightMinute = "0" + lightMinute;
if(lightHour.length() == 1) lightHour = "0" + lightHour;
homeScreenList = homeScreenListNew;
}
String darkMinute = String.valueOf(tinyDB.getInt("darkThemeTimeMinute"));
String darkHour = String.valueOf(tinyDB.getInt("darkThemeTimeHour"));
if(darkMinute.length() == 1) darkMinute = "0" + darkMinute;
if(darkHour.length() == 1) darkHour = "0" + darkHour;
if(!tinyDb.getString("timeStr").isEmpty()) {
tvDateTimeSelected.setText(tinyDb.getString("timeStr"));
}
activitySettingsAppearanceBinding.lightThemeSelectedTime.setText(ctx.getResources().getString(R.string.settingsThemeTimeSelectedHint, lightHour,
lightMinute));
activitySettingsAppearanceBinding.darkThemeSelectedTime.setText(ctx.getResources().getString(R.string.settingsThemeTimeSelectedHint, darkHour,
darkMinute));
activitySettingsAppearanceBinding.tvDateTimeSelected.setText(tinyDB.getString("timeStr"));
activitySettingsAppearanceBinding.customFontSelected.setText(tinyDB.getString("customFontStr", "Manrope"));
activitySettingsAppearanceBinding.themeSelected.setText(tinyDB.getString("themeStr", "Dark"));
if(!tinyDb.getString("codeBlockStr").isEmpty()) {
codeBlockSelected.setText(tinyDb.getString("codeBlockStr"));
}
if(!tinyDb.getString("homeScreenStr").isEmpty()) {
homeScreenSelected.setText(tinyDb.getString("homeScreenStr"));
}
if(!tinyDb.getString("customFontStr").isEmpty()) {
customFontSelected.setText(tinyDb.getString("customFontStr"));
}
if(!tinyDb.getString("themeStr").isEmpty()) {
themeSelected.setText(tinyDb.getString("themeStr"));
}
if(timeSelectedChoice == 0) {
timeSelectedChoice = tinyDb.getInt("timeId");
}
if(codeBlockSelectedChoice == 0) {
codeBlockSelectedChoice = tinyDb.getInt("codeBlockId");
}
if(homeScreenSelectedChoice == 0) {
homeScreenSelectedChoice = tinyDb.getInt("homeScreenId");
}
if(customFontSelectedChoice == 0) {
customFontSelectedChoice = tinyDb.getInt("customFontId", 1);
}
if(themeSelectedChoice == 0) {
themeSelectedChoice = tinyDb.getInt("themeId");
}
if(tinyDb.getBoolean("enableCounterBadges")) {
counterBadgesSwitch.setChecked(true);
if(tinyDB.getString("themeStr").startsWith("Auto")) {
darkTimeFrame.setVisibility(View.VISIBLE);
lightTimeFrame.setVisibility(View.VISIBLE);
}
else {
counterBadgesSwitch.setChecked(false);
darkTimeFrame.setVisibility(View.GONE);
lightTimeFrame.setVisibility(View.GONE);
}
timeSelectedChoice = tinyDB.getInt("timeId");
customFontSelectedChoice = tinyDB.getInt("customFontId", 1);
themeSelectedChoice = tinyDB.getInt("themeId");
counterBadgesSwitch.setChecked(tinyDB.getBoolean("enableCounterBadges"));
// counter badge switcher
counterBadgesSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
tinyDb.putBoolean("enableCounterBadges", true);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
else {
tinyDb.putBoolean("enableCounterBadges", false);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
tinyDB.putBoolean("enableCounterBadges", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
// theme selection dialog
@ -143,31 +105,34 @@ public class SettingsAppearanceActivity extends BaseActivity {
AlertDialog.Builder tsBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
tsBuilder.setTitle(getResources().getString(R.string.themeSelectorDialogTitle));
if(themeSelectedChoice != -1) {
tsBuilder.setCancelable(true);
}
else {
tsBuilder.setCancelable(false);
}
tsBuilder.setCancelable(themeSelectedChoice != -1);
tsBuilder.setSingleChoiceItems(themeList, themeSelectedChoice, (dialogInterfaceTheme, i) -> {
themeSelectedChoice = i;
themeSelected.setText(themeList[i]);
tinyDb.putString("themeStr", themeList[i]);
tinyDb.putInt("themeId", i);
activitySettingsAppearanceBinding.themeSelected.setText(themeList[i]);
tinyDB.putString("themeStr", themeList[i]);
tinyDB.putInt("themeId", i);
tinyDb.putBoolean("refreshParent", true);
tinyDB.putBoolean("refreshParent", true);
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceTheme.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = tsBuilder.create();
cfDialog.show();
});
lightTimeFrame.setOnClickListener(view -> {
LightTimePicker timePicker = new LightTimePicker();
timePicker.show(getSupportFragmentManager(), "timePicker");
});
darkTimeFrame.setOnClickListener(view -> {
DarkTimePicker timePicker = new DarkTimePicker();
timePicker.show(getSupportFragmentManager(), "timePicker");
});
// custom font dialog
@ -176,114 +141,24 @@ public class SettingsAppearanceActivity extends BaseActivity {
AlertDialog.Builder cfBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
cfBuilder.setTitle(R.string.settingsCustomFontSelectorDialogTitle);
if(customFontSelectedChoice != -1) {
cfBuilder.setCancelable(true);
}
else {
cfBuilder.setCancelable(false);
}
cfBuilder.setCancelable(customFontSelectedChoice != -1);
cfBuilder.setSingleChoiceItems(customFontList, customFontSelectedChoice, (dialogInterfaceCustomFont, i) -> {
customFontSelectedChoice = i;
customFontSelected.setText(customFontList[i]);
tinyDb.putString("customFontStr", customFontList[i]);
tinyDb.putInt("customFontId", i);
activitySettingsAppearanceBinding.customFontSelected.setText(customFontList[i]);
tinyDB.putString("customFontStr", customFontList[i]);
tinyDB.putInt("customFontId", i);
tinyDb.putBoolean("refreshParent", true);
tinyDB.putBoolean("refreshParent", true);
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceCustomFont.dismiss();
Toasty.success(appCtx, appCtx.getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = cfBuilder.create();
cfDialog.show();
});
// home screen dialog
homeScreenFrame.setOnClickListener(view -> {
AlertDialog.Builder hsBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
hsBuilder.setTitle(R.string.settingsHomeScreenSelectorDialogTitle);
if(homeScreenSelectedChoice != -1) {
hsBuilder.setCancelable(true);
}
else {
hsBuilder.setCancelable(false);
}
hsBuilder.setSingleChoiceItems(homeScreenList, homeScreenSelectedChoice, (dialogInterfaceHomeScreen, i) -> {
homeScreenSelectedChoice = i;
homeScreenSelected.setText(homeScreenList[i]);
tinyDb.putString("homeScreenStr", homeScreenList[i]);
tinyDb.putInt("homeScreenId", i);
dialogInterfaceHomeScreen.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog hsDialog = hsBuilder.create();
hsDialog.show();
});
// code block dialog
codeBlockFrame.setOnClickListener(view -> {
AlertDialog.Builder cBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
cBuilder.setTitle(R.string.settingsCodeBlockSelectorDialogTitle);
if(codeBlockSelectedChoice != -1) {
cBuilder.setCancelable(true);
}
else {
cBuilder.setCancelable(false);
}
cBuilder.setSingleChoiceItems(codeBlockList, codeBlockSelectedChoice, (dialogInterfaceCodeBlock, i) -> {
codeBlockSelectedChoice = i;
codeBlockSelected.setText(codeBlockList[i]);
tinyDb.putString("codeBlockStr", codeBlockList[i]);
tinyDb.putInt("codeBlockId", i);
switch(codeBlockList[i]) {
case "White - Black":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorWhite));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
break;
case "Grey - Black":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorAccent));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
break;
case "White - Grey":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorWhite));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.colorAccent));
break;
case "Dark - White":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorPrimary));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.colorWhite));
break;
default:
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorLightGreen));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
break;
}
dialogInterfaceCodeBlock.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cDialog = cBuilder.create();
cDialog.show();
});
// time and date dialog
@ -292,36 +167,30 @@ public class SettingsAppearanceActivity extends BaseActivity {
AlertDialog.Builder tBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
tBuilder.setTitle(R.string.settingsTimeSelectorDialogTitle);
if(timeSelectedChoice != -1) {
tBuilder.setCancelable(true);
}
else {
tBuilder.setCancelable(false);
}
tBuilder.setCancelable(timeSelectedChoice != -1);
tBuilder.setSingleChoiceItems(timeList, timeSelectedChoice, (dialogInterfaceTime, i) -> {
timeSelectedChoice = i;
tvDateTimeSelected.setText(timeList[i]);
tinyDb.putString("timeStr", timeList[i]);
tinyDb.putInt("timeId", i);
activitySettingsAppearanceBinding.tvDateTimeSelected.setText(timeList[i]);
tinyDB.putString("timeStr", timeList[i]);
tinyDB.putInt("timeId", i);
if("Normal".equals(timeList[i])) {
tinyDb.putString("dateFormat", "normal");
}
else {
tinyDb.putString("dateFormat", "pretty");
switch(i) {
case 0:
tinyDB.putString("dateFormat", "pretty");
break;
case 1:
tinyDB.putString("dateFormat", "normal");
break;
}
dialogInterfaceTime.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog tDialog = tBuilder.create();
tDialog.show();
});
}
@ -330,4 +199,54 @@ public class SettingsAppearanceActivity extends BaseActivity {
onClickListener = view -> finish();
}
public static class LightTimePicker extends DialogFragment implements TimePickerDialog.OnTimeSetListener {
TinyDB db = TinyDB.getInstance(getContext());
@NotNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int hour = db.getInt("lightThemeTimeHour");
int minute = db.getInt("lightThemeTimeMinute");
return new TimePickerDialog(getActivity(), this, hour, minute, true);
}
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
db.putInt("lightThemeTimeHour", hourOfDay);
db.putInt("lightThemeTimeMinute", minute);
db.putBoolean("refreshParent", true);
requireActivity().overridePendingTransition(0, 0);
this.dismiss();
Toasty.success(requireActivity().getApplicationContext(), requireContext().getResources().getString(R.string.settingsSave));
requireActivity().recreate();
}
}
public static class DarkTimePicker extends DialogFragment implements TimePickerDialog.OnTimeSetListener {
TinyDB db = TinyDB.getInstance(getContext());
@NotNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int hour = db.getInt("darkThemeTimeHour");
int minute = db.getInt("darkThemeTimeMinute");
return new TimePickerDialog(getActivity(), this, hour, minute, true);
}
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
db.putInt("darkThemeTimeHour", hourOfDay);
db.putInt("darkThemeTimeMinute", minute);
db.putBoolean("refreshParent", true);
requireActivity().overridePendingTransition(0, 0);
this.dismiss();
Toasty.success(requireActivity().getApplicationContext(), requireContext().getResources().getString(R.string.settingsSave));
requireActivity().recreate();
}
}
}

View File

@ -1,13 +1,11 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Switch;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsDraftsBinding;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.TinyDB;
/**
* Author M M Arif
@ -15,49 +13,28 @@ import org.mian.gitnex.helpers.TinyDB;
public class SettingsDraftsActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_drafts;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
ActivitySettingsDraftsBinding activitySettingsDraftsBinding = ActivitySettingsDraftsBinding.inflate(getLayoutInflater());
setContentView(activitySettingsDraftsBinding.getRoot());
ImageView closeActivity = findViewById(R.id.close);
ImageView closeActivity = activitySettingsDraftsBinding.close;
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
Switch commentsDeletionSwitch = findViewById(R.id.commentsDeletionSwitch);
if(tinyDb.getBoolean("draftsCommentsDeletionEnabled")) {
commentsDeletionSwitch.setChecked(true);
}
else {
commentsDeletionSwitch.setChecked(false);
}
activitySettingsDraftsBinding.commentsDeletionSwitch.setChecked(tinyDB.getBoolean("draftsCommentsDeletionEnabled"));
// delete comments on submit switcher
commentsDeletionSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(isChecked) {
tinyDb.putBoolean("draftsCommentsDeletionEnabled", true);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
else {
tinyDb.putBoolean("draftsCommentsDeletionEnabled", false);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
activitySettingsDraftsBinding.commentsDeletionSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
tinyDB.putBoolean("draftsCommentsDeletionEnabled", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
}

View File

@ -1,119 +0,0 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
/**
* Author M M Arif
*/
public class SettingsFileViewerActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
private static String[] fileViewerSourceCodeThemesList = {"Sublime", "Arduino Light", "Github", "Far ", "Ir Black", "Android Studio"};
private static int fileViewerSourceCodeThemesSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_fileview;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
final TinyDB tinyDb = new TinyDB(appCtx);
ImageView closeActivity = findViewById(R.id.close);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
final TextView fileViewerSourceCodeThemesSelected = findViewById(R.id.sourceCodeThemeSelected); // setter for fileviewer theme
LinearLayout sourceCodeThemeFrame = findViewById(R.id.sourceCodeThemeFrame);
Switch pdfModeSwitch = findViewById(R.id.switchPdfMode);
if(!tinyDb.getString("fileviewerSourceCodeThemeStr").isEmpty()) {
fileViewerSourceCodeThemesSelected.setText(tinyDb.getString("fileviewerSourceCodeThemeStr"));
}
if(fileViewerSourceCodeThemesSelectedChoice == 0) {
fileViewerSourceCodeThemesSelectedChoice = tinyDb.getInt("fileviewerThemeId");
}
if(tinyDb.getBoolean("enablePdfMode")) {
pdfModeSwitch.setChecked(true);
}
else {
pdfModeSwitch.setChecked(false);
}
// fileviewer srouce code theme selection dialog
sourceCodeThemeFrame.setOnClickListener(view -> {
AlertDialog.Builder fvtsBuilder = new AlertDialog.Builder(SettingsFileViewerActivity.this);
fvtsBuilder.setTitle(R.string.fileviewerSourceCodeThemeSelectorDialogTitle);
if(fileViewerSourceCodeThemesSelectedChoice != -1) {
fvtsBuilder.setCancelable(true);
}
else {
fvtsBuilder.setCancelable(false);
}
fvtsBuilder.setSingleChoiceItems(fileViewerSourceCodeThemesList, fileViewerSourceCodeThemesSelectedChoice, (dialogInterfaceTheme, i) -> {
fileViewerSourceCodeThemesSelectedChoice = i;
fileViewerSourceCodeThemesSelected.setText(fileViewerSourceCodeThemesList[i]);
tinyDb.putString("fileviewerSourceCodeThemeStr", fileViewerSourceCodeThemesList[i]);
tinyDb.putInt("fileviewerSourceCodeThemeId", i);
dialogInterfaceTheme.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = fvtsBuilder.create();
cfDialog.show();
});
// pdf night mode switcher
pdfModeSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(isChecked) {
tinyDb.putBoolean("enablePdfMode", true);
tinyDb.putString("enablePdfModeInit", "yes");
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
else {
tinyDb.putBoolean("enablePdfMode", false);
tinyDb.putString("enablePdfModeInit", "yes");
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -1,13 +1,12 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsGeneralBinding;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -19,65 +18,118 @@ import java.util.List;
public class SettingsGeneralActivity extends BaseActivity {
private ActivitySettingsGeneralBinding viewBinding;
private Context appCtx;
private View.OnClickListener onClickListener;
private List<String> defaultScreen;
private static int defaultScreenSelectedChoice = 0;
private List<String> homeScreenList;
private static int homeScreenSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_general;
}
private List<String> linkHandlerDefaultScreen;
private static int defaultLinkHandlerScreenSelectedChoice = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
viewBinding = ActivitySettingsGeneralBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
TinyDB tinyDb = new TinyDB(appCtx);
setContentView(viewBinding.getRoot());
initCloseListener();
viewBinding.close.setOnClickListener(onClickListener);
String[] defaultScreen_ = {getResources().getString(R.string.generalDeepLinkSelectedText), getResources().getString(R.string.navRepos), getResources().getString(R.string.navOrgs), getResources().getString(R.string.pageTitleNotifications), getResources().getString(R.string.navExplore)};
defaultScreen = new ArrayList<>(Arrays.asList(defaultScreen_));
// home screen
String[] appHomeDefaultScreen = getResources().getStringArray(R.array.appDefaultHomeScreen);
String[] linksArray = new String[defaultScreen.size()];
defaultScreen.toArray(linksArray);
String[] appHomeDefaultScreenNew = getResources().getStringArray(R.array.appDefaultHomeScreenNew);
if(!tinyDb.getString("defaultScreenStr").isEmpty()) {
viewBinding.generalDeepLinkSelected.setText(tinyDb.getString("defaultScreenStr"));
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.3")) {
appHomeDefaultScreen = appHomeDefaultScreenNew;
}
if(defaultScreenSelectedChoice == 0) {
defaultScreenSelectedChoice = tinyDb.getInt("defaultScreenId");
homeScreenList = new ArrayList<>(Arrays.asList(appHomeDefaultScreen));
String[] homeScreenArray = new String[homeScreenList.size()];
homeScreenList.toArray(homeScreenArray);
if(homeScreenSelectedChoice == 0) {
homeScreenSelectedChoice = tinyDB.getInt("homeScreenId");
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleMyRepos));
}
if(homeScreenSelectedChoice == 1) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleStarredRepos));
}
else if(homeScreenSelectedChoice == 2) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleOrganizations));
}
else if(homeScreenSelectedChoice == 3) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleRepositories));
}
else if(homeScreenSelectedChoice == 4) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleProfile));
}
else if(homeScreenSelectedChoice == 5) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleExplore));
}
else if(homeScreenSelectedChoice == 6) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.titleDrafts));
}
else if(homeScreenSelectedChoice == 7) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleNotifications));
}
viewBinding.homeScreenFrame.setOnClickListener(setDefaultHomeScreen -> {
AlertDialog.Builder hsBuilder = new AlertDialog.Builder(SettingsGeneralActivity.this);
hsBuilder.setTitle(R.string.settingsHomeScreenSelectorDialogTitle);
hsBuilder.setCancelable(homeScreenSelectedChoice != -1);
hsBuilder.setSingleChoiceItems(homeScreenArray, homeScreenSelectedChoice, (dialogInterfaceHomeScreen, i) -> {
homeScreenSelectedChoice = i;
viewBinding.homeScreenSelected.setText(homeScreenArray[i]);
tinyDB.putInt("homeScreenId", i);
dialogInterfaceHomeScreen.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog hsDialog = hsBuilder.create();
hsDialog.show();
});
// home screen
// link handler
String[] linkHandlerDefaultScreenList = getResources().getStringArray(R.array.linkHandlerDefaultScreen);
linkHandlerDefaultScreen = new ArrayList<>(Arrays.asList(linkHandlerDefaultScreenList));
String[] linksArray = new String[linkHandlerDefaultScreen.size()];
linkHandlerDefaultScreen.toArray(linksArray);
defaultLinkHandlerScreenSelectedChoice = tinyDB.getInt("defaultScreenId");
viewBinding.generalDeepLinkSelected.setText(linksArray[defaultLinkHandlerScreenSelectedChoice]);
viewBinding.setDefaultLinkHandler.setOnClickListener(setDefaultLinkHandler -> {
AlertDialog.Builder dlBuilder = new AlertDialog.Builder(SettingsGeneralActivity.this);
dlBuilder.setTitle(R.string.linkSelectorDialogTitle);
if(defaultScreenSelectedChoice != -1) {
dlBuilder.setCancelable(true);
}
else {
dlBuilder.setCancelable(false);
}
dlBuilder.setCancelable(defaultLinkHandlerScreenSelectedChoice != -1);
dlBuilder.setSingleChoiceItems(linksArray, defaultScreenSelectedChoice, (dialogInterfaceHomeScreen, i) -> {
dlBuilder.setSingleChoiceItems(linksArray, defaultLinkHandlerScreenSelectedChoice, (dialogInterfaceHomeScreen, i) -> {
defaultScreenSelectedChoice = i;
defaultLinkHandlerScreenSelectedChoice = i;
viewBinding.generalDeepLinkSelected.setText(linksArray[i]);
tinyDb.putString("defaultScreenStr", linksArray[i]);
tinyDb.putInt("defaultScreenId", i);
tinyDB.putInt("defaultScreenId", i);
dialogInterfaceHomeScreen.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
@ -85,9 +137,8 @@ public class SettingsGeneralActivity extends BaseActivity {
AlertDialog dlDialog = dlBuilder.create();
dlDialog.show();
});
// link handler
}
private void initCloseListener() { onClickListener = view -> finish(); }

View File

@ -0,0 +1,123 @@
package org.mian.gitnex.activities;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.NumberPicker;
import androidx.appcompat.app.AlertDialog;
import com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsNotificationsBinding;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.notifications.Notifications;
/**
* Template Author M M Arif
* Author opyale
*/
public class SettingsNotificationsActivity extends BaseActivity {
private ActivitySettingsNotificationsBinding viewBinding;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewBinding = ActivitySettingsNotificationsBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot());
View.OnClickListener onClickListener = viewClose -> finish();
viewBinding.close.setOnClickListener(onClickListener);
viewBinding.pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay)));
viewBinding.chooseColorState.setCardBackgroundColor(tinyDB.getInt("notificationsLightColor", Color.GREEN));
viewBinding.enableNotificationsMode.setChecked(tinyDB.getBoolean("notificationsEnabled", true));
viewBinding.enableLightsMode.setChecked(tinyDB.getBoolean("notificationsEnableLights", true));
viewBinding.enableVibrationMode.setChecked(tinyDB.getBoolean("notificationsEnableVibration", true));
viewBinding.enableNotificationsMode.setOnCheckedChangeListener((buttonView, isChecked) -> {
tinyDB.putBoolean("notificationsEnabled", isChecked);
if(isChecked) {
Notifications.startWorker(ctx);
} else {
Notifications.stopWorker(ctx);
}
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
});
// polling delay
viewBinding.pollingDelayFrame.setOnClickListener(v -> {
NumberPicker numberPicker = new NumberPicker(ctx);
numberPicker.setMinValue(Constants.minimumPollingDelay);
numberPicker.setMaxValue(Constants.maximumPollingDelay);
numberPicker.setValue(tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay));
numberPicker.setWrapSelectorWheel(true);
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle(getString(R.string.pollingDelayDialogHeaderText));
builder.setMessage(getString(R.string.pollingDelayDialogDescriptionText));
builder.setCancelable(true);
builder.setPositiveButton(getString(R.string.okButton), (dialog, which) -> {
tinyDB.putInt("pollingDelayMinutes", numberPicker.getValue());
Notifications.stopWorker(ctx);
Notifications.startWorker(ctx);
viewBinding.pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), numberPicker.getValue()));
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
});
builder.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss());
builder.setView(numberPicker);
builder.create().show();
});
// lights switcher
viewBinding.enableLightsMode.setOnCheckedChangeListener((buttonView, isChecked) -> {
tinyDB.putBoolean("notificationsEnableLights", isChecked);
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
});
// lights color chooser
viewBinding.chooseColorFrame.setOnClickListener(v -> {
ColorPicker colorPicker = new ColorPicker(SettingsNotificationsActivity.this);
colorPicker.setColor(tinyDB.getInt("notificationsLightColor", Color.GREEN));
colorPicker.setCallback(color -> {
tinyDB.putInt("notificationsLightColor", color);
viewBinding.chooseColorState.setCardBackgroundColor(color);
colorPicker.dismiss();
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
});
colorPicker.show();
});
// vibration switcher
viewBinding.enableVibrationMode.setOnCheckedChangeListener((buttonView, isChecked) -> {
tinyDB.putBoolean("notificationsEnableVibration", isChecked);
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
});
}
}

View File

@ -1,12 +1,10 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Switch;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.databinding.ActivitySettingsReportsBinding;
import org.mian.gitnex.helpers.Toasty;
/**
@ -15,51 +13,29 @@ import org.mian.gitnex.helpers.Toasty;
public class SettingsReportsActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_reporting;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
ActivitySettingsReportsBinding activitySettingsReportsBinding = ActivitySettingsReportsBinding.inflate(getLayoutInflater());
setContentView(activitySettingsReportsBinding.getRoot());
ImageView closeActivity = findViewById(R.id.close);
ImageView closeActivity = activitySettingsReportsBinding.close;
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
Switch crashReportsSwitch = findViewById(R.id.crashReportsSwitch);
if(tinyDb.getBoolean("crashReportingEnabled")) {
crashReportsSwitch.setChecked(true);
}
else {
crashReportsSwitch.setChecked(false);
}
activitySettingsReportsBinding.crashReportsSwitch.setChecked(tinyDB.getBoolean("crashReportingEnabled"));
// crash reports switcher
crashReportsSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(isChecked) {
tinyDb.putBoolean("crashReportingEnabled", true);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
else {
tinyDb.putBoolean("crashReportingEnabled", false);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
activitySettingsReportsBinding.crashReportsSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
tinyDB.putBoolean("crashReportingEnabled", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
}
private void initCloseListener() {

View File

@ -1,24 +1,27 @@
package org.mian.gitnex.activities;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.biometric.BiometricManager;
import com.google.android.material.switchmaterial.SwitchMaterial;
import org.apache.commons.io.FileUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.databinding.ActivitySettingsSecurityBinding;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.helpers.ssl.MemorizingTrustManager;
import org.mian.gitnex.notifications.NotificationsMaster;
import java.io.File;
import java.io.IOException;
import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG;
import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL;
/**
* Author M M Arif
@ -26,73 +29,124 @@ import java.io.IOException;
public class SettingsSecurityActivity extends BaseActivity {
private Context appCtx;
private Context ctx = this;
private View.OnClickListener onClickListener;
private static String[] cacheSizeDataList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"};
private static String[] cacheSizeDataList;
private static int cacheSizeDataSelectedChoice = 0;
private static String[] cacheSizeImagesList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"};
private static String[] cacheSizeImagesList;
private static int cacheSizeImagesSelectedChoice = 0;
private static int MINIMUM_POLLING_DELAY = 1;
private static int DEFAULT_POLLING_DELAY = 20;
private static int MAXIMUM_POLLING_DELAY = 720;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_security;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
String currentVersion = tinyDb.getString("giteaVersion");
ActivitySettingsSecurityBinding activitySettingsSecurityBinding = ActivitySettingsSecurityBinding.inflate(getLayoutInflater());
setContentView(activitySettingsSecurityBinding.getRoot());
ImageView closeActivity = findViewById(R.id.close);
ImageView closeActivity = activitySettingsSecurityBinding.close;
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
TextView cacheSizeDataSelected = findViewById(R.id.cacheSizeDataSelected); // setter for data cache size
TextView cacheSizeImagesSelected = findViewById(R.id.cacheSizeImagesSelected); // setter for images cache size
TextView clearCacheSelected = findViewById(R.id.clearCacheSelected); // setter for clear cache
TextView pollingDelaySelected = findViewById(R.id.pollingDelaySelected);
TextView cacheSizeDataSelected = activitySettingsSecurityBinding.cacheSizeDataSelected; // setter for data cache size
TextView cacheSizeImagesSelected = activitySettingsSecurityBinding.cacheSizeImagesSelected; // setter for images cache size
TextView clearCacheSelected = activitySettingsSecurityBinding.clearCacheSelected; // setter for clear cache
LinearLayout certsFrame = findViewById(R.id.certsFrame);
LinearLayout pollingDelayFrame = findViewById(R.id.pollingDelayFrame);
LinearLayout cacheSizeDataFrame = findViewById(R.id.cacheSizeDataSelectionFrame);
LinearLayout cacheSizeImagesFrame = findViewById(R.id.cacheSizeImagesSelectionFrame);
LinearLayout clearCacheFrame = findViewById(R.id.clearCacheSelectionFrame);
LinearLayout certsFrame = activitySettingsSecurityBinding.certsFrame;
LinearLayout cacheSizeDataFrame = activitySettingsSecurityBinding.cacheSizeDataSelectionFrame;
LinearLayout cacheSizeImagesFrame = activitySettingsSecurityBinding.cacheSizeImagesSelectionFrame;
LinearLayout clearCacheFrame = activitySettingsSecurityBinding.clearCacheSelectionFrame;
if(!tinyDb.getString("cacheSizeStr").isEmpty()) {
cacheSizeDataSelected.setText(tinyDb.getString("cacheSizeStr"));
SwitchMaterial switchBiometric = activitySettingsSecurityBinding.switchBiometric;
cacheSizeDataList = getResources().getStringArray(R.array.cacheSizeList);
cacheSizeImagesList = getResources().getStringArray(R.array.cacheSizeList);
if(!tinyDB.getString("cacheSizeStr").isEmpty()) {
cacheSizeDataSelected.setText(tinyDB.getString("cacheSizeStr"));
}
if(!tinyDb.getString("cacheSizeImagesStr").isEmpty()) {
cacheSizeImagesSelected.setText(tinyDb.getString("cacheSizeImagesStr"));
if(!tinyDB.getString("cacheSizeImagesStr").isEmpty()) {
cacheSizeImagesSelected.setText(tinyDB.getString("cacheSizeImagesStr"));
}
if(cacheSizeDataSelectedChoice == 0) {
cacheSizeDataSelectedChoice = tinyDb.getInt("cacheSizeId");
cacheSizeDataSelectedChoice = tinyDB.getInt("cacheSizeId");
}
if(cacheSizeImagesSelectedChoice == 0) {
cacheSizeImagesSelectedChoice = tinyDb.getInt("cacheSizeImagesId");
cacheSizeImagesSelectedChoice = tinyDB.getInt("cacheSizeImagesId");
}
if(new Version(currentVersion).less("1.12.3")) {
pollingDelayFrame.setVisibility(View.GONE);
}
switchBiometric.setChecked(tinyDB.getBoolean("biometricStatus"));
pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), tinyDb.getInt("pollingDelayMinutes", DEFAULT_POLLING_DELAY)));
// biometric switcher
switchBiometric.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(isChecked) {
BiometricManager biometricManager = BiometricManager.from(ctx);
KeyguardManager keyguardManager = (KeyguardManager) ctx.getSystemService(Context.KEYGUARD_SERVICE);
if (!keyguardManager.isDeviceSecure()) {
switch(biometricManager.canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL)) {
case BiometricManager.BIOMETRIC_SUCCESS:
tinyDB.putBoolean("biometricStatus", true);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
break;
case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
case BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED:
case BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED:
case BiometricManager.BIOMETRIC_STATUS_UNKNOWN:
tinyDB.putBoolean("biometricStatus", false);
switchBiometric.setChecked(false);
Toasty.error(appCtx, getResources().getString(R.string.biometricNotSupported));
break;
case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
tinyDB.putBoolean("biometricStatus", false);
switchBiometric.setChecked(false);
Toasty.error(appCtx, getResources().getString(R.string.biometricNotAvailable));
break;
case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
tinyDB.putBoolean("biometricStatus", false);
switchBiometric.setChecked(false);
Toasty.info(appCtx, getResources().getString(R.string.enrollBiometric));
break;
}
}
else {
tinyDB.putBoolean("biometricStatus", true);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
}
else {
tinyDB.putBoolean("biometricStatus", false);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
}
else {
tinyDB.putBoolean("biometricStatus", false);
Toasty.success(appCtx, getResources().getString(R.string.biometricNotSupported));
}
});
// clear cache setter
File cacheDir = appCtx.getCacheDir();
@ -113,14 +167,11 @@ public class SettingsSecurityActivity extends BaseActivity {
FileUtils.mkdir(cacheDir.getAbsolutePath());
this.recreate();
this.overridePendingTransition(0, 0);
}
catch (IOException e) {
Log.e("SettingsSecurity", e.toString());
}
});
builder.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss());
@ -134,28 +185,21 @@ public class SettingsSecurityActivity extends BaseActivity {
AlertDialog.Builder tsBuilder = new AlertDialog.Builder(SettingsSecurityActivity.this);
tsBuilder.setTitle(getResources().getString(R.string.cacheSizeImagesDialogHeader));
if(cacheSizeImagesSelectedChoice != -1) {
tsBuilder.setCancelable(true);
}
else {
tsBuilder.setCancelable(false);
}
tsBuilder.setCancelable(cacheSizeImagesSelectedChoice != -1);
tsBuilder.setSingleChoiceItems(cacheSizeImagesList, cacheSizeImagesSelectedChoice, (dialogInterfaceTheme, i) -> {
cacheSizeImagesSelectedChoice = i;
cacheSizeImagesSelected.setText(cacheSizeImagesList[i]);
tinyDb.putString("cacheSizeImagesStr", cacheSizeImagesList[i]);
tinyDb.putInt("cacheSizeImagesId", i);
tinyDB.putString("cacheSizeImagesStr", cacheSizeImagesList[i]);
tinyDB.putInt("cacheSizeImagesId", i);
dialogInterfaceTheme.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = tsBuilder.create();
cfDialog.show();
});
// cache size data selection dialog
@ -164,28 +208,21 @@ public class SettingsSecurityActivity extends BaseActivity {
AlertDialog.Builder tsBuilder = new AlertDialog.Builder(SettingsSecurityActivity.this);
tsBuilder.setTitle(getResources().getString(R.string.cacheSizeDataDialogHeader));
if(cacheSizeDataSelectedChoice != -1) {
tsBuilder.setCancelable(true);
}
else {
tsBuilder.setCancelable(false);
}
tsBuilder.setCancelable(cacheSizeDataSelectedChoice != -1);
tsBuilder.setSingleChoiceItems(cacheSizeDataList, cacheSizeDataSelectedChoice, (dialogInterfaceTheme, i) -> {
cacheSizeDataSelectedChoice = i;
cacheSizeDataSelected.setText(cacheSizeDataList[i]);
tinyDb.putString("cacheSizeStr", cacheSizeDataList[i]);
tinyDb.putInt("cacheSizeId", i);
tinyDB.putString("cacheSizeStr", cacheSizeDataList[i]);
tinyDB.putInt("cacheSizeId", i);
dialogInterfaceTheme.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = tsBuilder.create();
cfDialog.show();
});
// certs deletion
@ -199,53 +236,18 @@ public class SettingsSecurityActivity extends BaseActivity {
appCtx.getSharedPreferences(MemorizingTrustManager.KEYSTORE_NAME, Context.MODE_PRIVATE).edit().remove(MemorizingTrustManager.KEYSTORE_KEY).apply();
tinyDb.putBoolean("loggedInMode", false);
tinyDb.remove("basicAuthPassword");
tinyDb.putBoolean("basicAuthFlag", false);
tinyDB.putBoolean("loggedInMode", false);
tinyDB.remove("basicAuthPassword");
tinyDB.putBoolean("basicAuthFlag", false);
Intent loginActivityIntent = new Intent().setClass(appCtx, LoginActivity.class);
loginActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
appCtx.startActivity(loginActivityIntent);
});
builder.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss());
builder.create().show();
});
// polling delay
pollingDelayFrame.setOnClickListener(v -> {
NumberPicker numberPicker = new NumberPicker(ctx);
numberPicker.setMinValue(MINIMUM_POLLING_DELAY);
numberPicker.setMaxValue(MAXIMUM_POLLING_DELAY);
numberPicker.setValue(tinyDb.getInt("pollingDelayMinutes", DEFAULT_POLLING_DELAY));
numberPicker.setWrapSelectorWheel(true);
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle(getString(R.string.pollingDelayDialogHeaderText));
builder.setMessage(getString(R.string.pollingDelayDialogDescriptionText));
builder.setCancelable(true);
builder.setPositiveButton(getString(R.string.okButton), (dialog, which) -> {
tinyDb.putInt("pollingDelayMinutes", numberPicker.getValue());
NotificationsMaster.fireWorker(ctx);
NotificationsMaster.hireWorker(ctx);
pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), numberPicker.getValue()));
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
builder.setNeutralButton(R.string.cancelButton, null);
builder.setView(numberPicker);
builder.create().show();
});
}
private void initCloseListener() {

View File

@ -1,6 +1,5 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@ -10,8 +9,11 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.databinding.ActivitySettingsTranslationBinding;
import org.mian.gitnex.helpers.Toasty;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.TreeMap;
/**
* Author M M Arif
@ -19,36 +21,33 @@ import org.mian.gitnex.helpers.Toasty;
public class SettingsTranslationActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
private static String[] langList = {"English", "Arabic", "Chinese", "Czech", "Finnish", "French", "German", "Italian", "Latvian", "Persian",
"Polish", "Portuguese/Brazilian", "Russian", "Serbian", "Spanish", "Turkish", "Ukrainian"};
private static int langSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_translation;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
LinkedHashMap<String, String> langs = new LinkedHashMap<>();
langs.put("", getString(R.string.settingsLanguageSystem));
for(String langCode : getResources().getStringArray(R.array.languages)) {
langs.put(langCode, getLanguageDisplayName(langCode));
}
ImageView closeActivity = findViewById(R.id.close);
ActivitySettingsTranslationBinding activitySettingsTranslationBinding = ActivitySettingsTranslationBinding.inflate(getLayoutInflater());
setContentView(activitySettingsTranslationBinding.getRoot());
ImageView closeActivity = activitySettingsTranslationBinding.close;
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
final TextView tvLanguageSelected = findViewById(R.id.tvLanguageSelected); // setter for en, fr
TextView helpTranslate = findViewById(R.id.helpTranslate);
final TextView tvLanguageSelected = activitySettingsTranslationBinding.tvLanguageSelected; // setter for en, fr
TextView helpTranslate = activitySettingsTranslationBinding.helpTranslate;
LinearLayout langFrame = findViewById(R.id.langFrame);
LinearLayout langFrame = activitySettingsTranslationBinding.langFrame;
helpTranslate.setOnClickListener(v12 -> {
@ -60,13 +59,9 @@ public class SettingsTranslationActivity extends BaseActivity {
});
if(!tinyDb.getString("localeStr").isEmpty()) {
tvLanguageSelected.setText(tinyDb.getString("localeStr"));
}
tvLanguageSelected.setText(tinyDB.getString("localeStr"));
if(langSelectedChoice == 0) {
langSelectedChoice = tinyDb.getInt("langId");
}
langSelectedChoice = tinyDB.getInt("langId");
// language dialog
langFrame.setOnClickListener(view -> {
@ -74,89 +69,27 @@ public class SettingsTranslationActivity extends BaseActivity {
AlertDialog.Builder lBuilder = new AlertDialog.Builder(SettingsTranslationActivity.this);
lBuilder.setTitle(R.string.settingsLanguageSelectorDialogTitle);
if(langSelectedChoice != -1) {
lBuilder.setCancelable(true);
}
else {
lBuilder.setCancelable(false);
}
lBuilder.setCancelable(langSelectedChoice != -1);
lBuilder.setSingleChoiceItems(langList, langSelectedChoice, (dialogInterface, i) -> {
lBuilder.setSingleChoiceItems(langs.values().toArray(new String[0]), langSelectedChoice, (dialogInterface, i) -> {
langSelectedChoice = i;
tvLanguageSelected.setText(langList[i]);
tinyDb.putString("localeStr", langList[i]);
tinyDb.putInt("langId", i);
String selectedLanguage = langs.keySet().toArray(new String[0])[i];
tinyDB.putString("localeStr", langs.get(selectedLanguage));
tinyDB.putInt("langId", i);
tinyDB.putString("locale", selectedLanguage);
switch(langList[i]) {
case "Arabic":
tinyDb.putString("locale", "ar");
break;
case "Chinese":
tinyDb.putString("locale", "zh");
break;
case "Czech":
tinyDb.putString("locale", "cs");
break;
case "Finnish":
tinyDb.putString("locale", "fi");
break;
case "French":
tinyDb.putString("locale", "fr");
break;
case "German":
tinyDb.putString("locale", "de");
break;
case "Italian":
tinyDb.putString("locale", "it");
break;
case "Latvian":
tinyDb.putString("locale", "lv");
break;
case "Persian":
tinyDb.putString("locale", "fa");
break;
case "Polish":
tinyDb.putString("locale", "pl");
break;
case "Portuguese/Brazilian":
tinyDb.putString("locale", "pt");
break;
case "Russian":
tinyDb.putString("locale", "ru");
break;
case "Serbian":
tinyDb.putString("locale", "sr");
break;
case "Spanish":
tinyDb.putString("locale", "es");
break;
case "Turkish":
tinyDb.putString("locale", "tr");
break;
case "Ukrainian":
tinyDb.putString("locale", "uk");
break;
default:
tinyDb.putString("locale", "en");
break;
}
tinyDb.putBoolean("refreshParent", true);
this.recreate();
tinyDB.putBoolean("refreshParent", true);
this.overridePendingTransition(0, 0);
dialogInterface.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
this.recreate();
});
lBuilder.setNeutralButton(getString(R.string.cancelButton), null);
AlertDialog lDialog = lBuilder.create();
lDialog.show();
});
}
private void initCloseListener() {
@ -164,4 +97,10 @@ public class SettingsTranslationActivity extends BaseActivity {
onClickListener = view -> finish();
}
private static String getLanguageDisplayName(String langCode) {
Locale english = new Locale("en");
Locale translated = new Locale(langCode);
return String.format("%s (%s)", translated.getDisplayName(translated), translated.getDisplayName(english));
}
}

View File

@ -0,0 +1,171 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.RecyclerView;
import com.google.gson.JsonElement;
import org.apache.commons.lang3.StringUtils;
import org.gitnex.tea4j.models.CronTasks;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.List;
import java.util.Locale;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class AdminCronTasksAdapter extends RecyclerView.Adapter<AdminCronTasksAdapter.CronTasksViewHolder> {
private final List<CronTasks> tasksList;
private static TinyDB tinyDb;
static class CronTasksViewHolder extends RecyclerView.ViewHolder {
private CronTasks cronTasks;
private final TextView taskName;
private CronTasksViewHolder(View itemView) {
super(itemView);
Context ctx = itemView.getContext();
final Locale locale = ctx.getResources().getConfiguration().locale;
final String timeFormat = tinyDb.getString("dateFormat");
ImageView runTask = itemView.findViewById(R.id.runTask);
taskName = itemView.findViewById(R.id.taskName);
LinearLayout cronTasksInfo = itemView.findViewById(R.id.cronTasksInfo);
LinearLayout cronTasksRun = itemView.findViewById(R.id.cronTasksRun);
cronTasksInfo.setOnClickListener(taskInfo -> {
String nextRun = "";
String lastRun = "";
if(cronTasks.getNext() != null) {
nextRun = TimeHelper.formatTime(cronTasks.getNext(), locale, timeFormat, ctx);
}
if(cronTasks.getPrev() != null) {
lastRun = TimeHelper.formatTime(cronTasks.getPrev(), locale, timeFormat, ctx);
}
View view = LayoutInflater.from(ctx).inflate(R.layout.layout_cron_task_info, null);
TextView taskScheduleContent = view.findViewById(R.id.taskScheduleContent);
TextView nextRunContent = view.findViewById(R.id.nextRunContent);
TextView lastRunContent = view.findViewById(R.id.lastRunContent);
TextView execTimeContent = view.findViewById(R.id.execTimeContent);
taskScheduleContent.setText(cronTasks.getSchedule());
nextRunContent.setText(nextRun);
lastRunContent.setText(lastRun);
execTimeContent.setText(String.valueOf(cronTasks.getExec_times()));
AlertDialog.Builder alertDialog = new AlertDialog.Builder(ctx);
alertDialog.setTitle(StringUtils.capitalize(cronTasks.getName().replace("_", " ")));
alertDialog.setView(view);
alertDialog.setPositiveButton(ctx.getString(R.string.close), null);
alertDialog.create().show();
});
cronTasksRun.setOnClickListener(taskInfo -> {
runCronTask(ctx, cronTasks.getName());
});
}
}
public AdminCronTasksAdapter(Context ctx, List<CronTasks> tasksListMain) {
tinyDb = TinyDB.getInstance(ctx);
this.tasksList = tasksListMain;
}
@NonNull
@Override
public AdminCronTasksAdapter.CronTasksViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_admin_cron_tasks, parent, false);
return new AdminCronTasksAdapter.CronTasksViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull AdminCronTasksAdapter.CronTasksViewHolder holder, int position) {
CronTasks currentItem = tasksList.get(position);
holder.cronTasks = currentItem;
holder.taskName.setText(StringUtils.capitalize(currentItem.getName().replace("_", " ")));
}
private static void runCronTask(final Context ctx, final String taskName) {
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
Call<JsonElement> call = RetrofitClient
.getApiInterface(ctx)
.adminRunCronTask(instanceToken, taskName);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
switch(response.code()) {
case 204:
Toasty.success(ctx, ctx.getString(R.string.adminCronTaskSuccessMsg, taskName));
break;
case 401:
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getString(R.string.alertDialogTokenRevokedTitle),
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
break;
case 404:
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
break;
default:
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
}
});
}
@Override
public int getItemCount() {
return tasksList.size();
}
}

View File

@ -1,6 +1,8 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -9,12 +11,15 @@ import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo;
import java.util.ArrayList;
import java.util.List;
@ -24,19 +29,22 @@ import java.util.List;
public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdapter.UsersViewHolder> implements Filterable {
private List<UserInfo> usersList;
private Context mCtx;
private List<UserInfo> usersListFull;
private final List<UserInfo> usersList;
private final Context context;
private final List<UserInfo> usersListFull;
static class UsersViewHolder extends RecyclerView.ViewHolder {
class UsersViewHolder extends RecyclerView.ViewHolder {
private ImageView userAvatar;
private TextView userFullName;
private TextView userEmail;
private ImageView userRole;
private TextView userName;
private String userLoginId;
private final ImageView userAvatar;
private final TextView userFullName;
private final TextView userEmail;
private final ImageView userRole;
private final TextView userName;
private UsersViewHolder(View itemView) {
super(itemView);
userAvatar = itemView.findViewById(R.id.userAvatar);
@ -45,11 +53,22 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
userEmail = itemView.findViewById(R.id.userEmail);
userRole = itemView.findViewById(R.id.userRole);
itemView.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userLoginId);
context.startActivity(intent);
});
userAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
return true;
});
}
}
public AdminGetUsersAdapter(Context mCtx, List<UserInfo> usersListMain) {
this.mCtx = mCtx;
public AdminGetUsersAdapter(Context ctx, List<UserInfo> usersListMain) {
this.context = ctx;
this.usersList = usersListMain;
usersListFull = new ArrayList<>(usersList);
}
@ -57,6 +76,7 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
@NonNull
@Override
public AdminGetUsersAdapter.UsersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_admin_users, parent, false);
return new AdminGetUsersAdapter.UsersViewHolder(v);
}
@ -65,40 +85,49 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
public void onBindViewHolder(@NonNull AdminGetUsersAdapter.UsersViewHolder holder, int position) {
UserInfo currentItem = usersList.get(position);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
holder.userLoginId = currentItem.getLogin();
if(!currentItem.getFullname().equals("")) {
holder.userFullName.setText(currentItem.getFullname());
holder.userName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getUsername()));
holder.userFullName.setText(Html.fromHtml(currentItem.getFullname()));
holder.userName.setText(context.getResources().getString(R.string.usernameWithAt, currentItem.getUsername()));
}
else {
holder.userFullName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getUsername()));
holder.userFullName.setText(context.getResources().getString(R.string.usernameWithAt, currentItem.getUsername()));
holder.userName.setVisibility(View.GONE);
}
if(!currentItem.getEmail().equals("")) {
holder.userEmail.setText(currentItem.getEmail());
}
else {
holder.userEmail.setVisibility(View.GONE);
}
if(currentItem.getIs_admin()) {
holder.userRole.setVisibility(View.VISIBLE);
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.textColor(mCtx.getResources().getColor(R.color.colorWhite))
.textColor(ResourcesCompat.getColor(context.getResources(), R.color.colorWhite, null))
.fontSize(44)
.width(180)
.height(60)
.endConfig()
.buildRoundRect(mCtx.getResources().getString(R.string.userRoleAdmin).toLowerCase(), mCtx.getResources().getColor(R.color.releasePre), 8);
.buildRoundRect(context.getResources().getString(R.string.userRoleAdmin).toLowerCase(), ResourcesCompat.getColor(context.getResources(), R.color.releasePre, null), 8);
holder.userRole.setImageDrawable(drawable);
}
else {
holder.userRole.setVisibility(View.GONE);
}
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
PicassoService.getInstance(context).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
}
@Override
@ -111,14 +140,15 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
return usersFilter;
}
private Filter usersFilter = new Filter() {
private final Filter usersFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<UserInfo> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(usersListFull);
} else {
}
else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (UserInfo item : usersListFull) {
@ -136,6 +166,7 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
usersList.clear();
usersList.addAll((List) results.values);
notifyDataSetChanged();

View File

@ -1,6 +1,7 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -9,10 +10,11 @@ import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.Collaborators;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.Collaborators;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
@ -23,21 +25,21 @@ import java.util.List;
public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdapter.AssigneesViewHolder> {
private Context mCtx;
private List<Collaborators> assigneesList;
private final Context context;
private final List<Collaborators> assigneesList;
private List<String> assigneesStrings = new ArrayList<>();
private List<String> currentAssignees;
private AssigneesListAdapterListener assigneesListener;
private final AssigneesListAdapterListener assigneesListener;
public interface AssigneesListAdapterListener {
void assigneesInterface(List<String> data);
}
public AssigneesListAdapter(Context mCtx, List<Collaborators> dataMain, AssigneesListAdapterListener assigneesListener, List<String> currentAssignees) {
public AssigneesListAdapter(Context ctx, List<Collaborators> dataMain, AssigneesListAdapterListener assigneesListener, List<String> currentAssignees) {
this.mCtx = mCtx;
this.context = ctx;
this.assigneesList = dataMain;
this.assigneesListener = assigneesListener;
this.currentAssignees = currentAssignees;
@ -45,17 +47,18 @@ public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdap
static class AssigneesViewHolder extends RecyclerView.ViewHolder {
private CheckBox assigneesSelection;
private TextView assigneesName;
private ImageView assigneesAvatar;
private final CheckBox assigneesSelection;
private final TextView assigneesName;
private final ImageView assigneesAvatar;
private AssigneesViewHolder(View itemView) {
super(itemView);
this.setIsRecyclable(false);
assigneesSelection = itemView.findViewById(R.id.assigneesSelection);
assigneesName = itemView.findViewById(R.id.assigneesName);
assigneesAvatar = itemView.findViewById(R.id.assigneesAvatar);
}
}
@ -71,15 +74,18 @@ public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdap
public void onBindViewHolder(@NonNull AssigneesListAdapter.AssigneesViewHolder holder, int position) {
Collaborators currentItem = assigneesList.get(position);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
if(currentItem.getFull_name().equals("")) {
holder.assigneesName.setText(currentItem.getLogin());
}
else {
holder.assigneesName.setText(currentItem.getFull_name());
holder.assigneesName.setText(Html.fromHtml(currentItem.getFull_name()));
}
PicassoService
.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(holder.assigneesAvatar);
.getInstance(context).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(180, 180).centerCrop().into(holder.assigneesAvatar);
for(int i = 0; i < assigneesList.size(); i++) {
@ -90,6 +96,7 @@ public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdap
}
currentAssignees = new ArrayList<>(new LinkedHashSet<>(currentAssignees));
for(int i = 0; i < currentAssignees.size(); i++) {
if(currentAssignees.contains(currentItem.getLogin())) {
@ -98,6 +105,7 @@ public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdap
assigneesStrings.add(currentAssignees.get(i));
}
}
assigneesListener.assigneesInterface(assigneesStrings);
holder.assigneesSelection.setOnCheckedChangeListener((buttonView, isChecked) -> {
@ -119,6 +127,7 @@ public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdap
@Override
public int getItemCount() {
return assigneesList.size();
}

View File

@ -2,15 +2,19 @@ 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.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import org.gitnex.tea4j.models.Collaborators;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import java.util.List;
@ -20,22 +24,37 @@ import java.util.List;
public class CollaboratorsAdapter extends BaseAdapter {
private List<Collaborators> collaboratorsList;
private Context mCtx;
private final List<Collaborators> collaboratorsList;
private final Context context;
private class ViewHolder {
private ImageView collaboratorAvatar;
private TextView collaboratorName;
private String userLoginId;
private final ImageView collaboratorAvatar;
private final TextView collaboratorName;
ViewHolder(View v) {
collaboratorAvatar = v.findViewById(R.id.collaboratorAvatar);
collaboratorName = v.findViewById(R.id.collaboratorName);
collaboratorAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userLoginId);
context.startActivity(intent);
});
collaboratorAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
return true;
});
}
}
public CollaboratorsAdapter(Context mCtx, List<Collaborators> collaboratorsListMain) {
this.mCtx = mCtx;
public CollaboratorsAdapter(Context ctx, List<Collaborators> collaboratorsListMain) {
this.context = ctx;
this.collaboratorsList = collaboratorsListMain;
}
@ -61,28 +80,35 @@ public class CollaboratorsAdapter extends BaseAdapter {
ViewHolder viewHolder = null;
if (finalView == null) {
finalView = LayoutInflater.from(mCtx).inflate(R.layout.list_collaborators, null);
finalView = LayoutInflater.from(context).inflate(R.layout.list_collaborators, null);
viewHolder = new ViewHolder(finalView);
finalView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) finalView.getTag();
}
initData(viewHolder, position);
return finalView;
}
private void initData(ViewHolder viewHolder, int position) {
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
Collaborators currentItem = collaboratorsList.get(position);
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.collaboratorAvatar);
PicassoService.getInstance(context).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(180, 180).centerCrop().into(viewHolder.collaboratorAvatar);
viewHolder.userLoginId = currentItem.getLogin();
if(!currentItem.getFull_name().equals("")) {
viewHolder.collaboratorName.setText(currentItem.getFull_name());
viewHolder.collaboratorName.setText(Html.fromHtml(currentItem.getFull_name()));
}
else {
viewHolder.collaboratorName.setText(currentItem.getLogin());
}

View File

@ -11,11 +11,12 @@ import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.Commits;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Commits;
import java.util.List;
import java.util.Locale;
@ -25,7 +26,7 @@ import java.util.Locale;
public class CommitsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context ctx;
private final Context context;
private final int TYPE_LOAD = 0;
private List<Commits> commitsList;
private CommitsAdapter.OnLoadMoreListener loadMoreListener;
@ -34,16 +35,15 @@ public class CommitsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
public CommitsAdapter(Context ctx, List<Commits> commitsListMain) {
this.ctx = ctx;
this.context = ctx;
this.commitsList = commitsListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(ctx);
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new CommitsHolder(inflater.inflate(R.layout.list_commits, parent, false));
@ -51,25 +51,19 @@ public class CommitsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
else {
return new 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) {
((CommitsHolder) holder).bindData(commitsList.get(position));
}
}
@Override
@ -81,14 +75,12 @@ public class CommitsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
else {
return 1;
}
}
@Override
public int getItemCount() {
return commitsList.size();
}
class CommitsHolder extends RecyclerView.ViewHolder {
@ -106,27 +98,23 @@ public class CommitsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
commitCommitter = itemView.findViewById(R.id.commitCommitterVw);
commitDate = itemView.findViewById(R.id.commitDateVw);
commitHtmlUrl = itemView.findViewById(R.id.commitHtmlUrlVw);
}
@SuppressLint("SetTextI18n")
void bindData(Commits commitsModel) {
final TinyDB tinyDb = new TinyDB(ctx);
final String locale = tinyDb.getString("locale");
final TinyDB tinyDb = TinyDB.getInstance(context);
Locale locale = context.getResources().getConfiguration().locale;
final String timeFormat = tinyDb.getString("dateFormat");
commitTitle.setText(commitsModel.getCommit().getMessage());
commitCommitter.setText(ctx.getString(R.string.commitCommittedBy, commitsModel.getCommit().getCommitter().getName()));
commitDate.setText(TimeHelper.formatTime(commitsModel.getCommit().getCommitter().getDate(), new Locale(locale), timeFormat, ctx));
commitTitle.setText(EmojiParser.parseToUnicode(commitsModel.getCommit().getMessage()));
commitCommitter.setText(context.getString(R.string.commitCommittedBy, commitsModel.getCommit().getCommitter().getName()));
commitDate.setText(TimeHelper.formatTime(commitsModel.getCommit().getCommitter().getDate(), locale, timeFormat, context));
if(timeFormat.equals("pretty")) {
commitDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(commitsModel.getCommit().getCommitter().getDate()), ctx));
commitDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(commitsModel.getCommit().getCommitter().getDate()), context));
}
commitHtmlUrl.setOnClickListener(v -> ctx.startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse(commitsModel.getHtml_url()))));
commitHtmlUrl.setOnClickListener(v -> context.startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse(commitsModel.getHtml_url()))));
}
}
@ -134,41 +122,29 @@ public class CommitsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
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(CommitsAdapter.OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<Commits> list) {
commitsList = list;
notifyDataSetChanged();
}
}

View File

@ -1,59 +0,0 @@
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

@ -2,8 +2,8 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
@ -11,12 +11,17 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.text.HtmlCompat;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.database.models.DraftWithRepository;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.List;
@ -28,21 +33,16 @@ import java.util.List;
public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsViewHolder> {
private List<DraftWithRepository> draftsList;
private FragmentManager fragmentManager;
private Context mCtx;
private final FragmentManager fragmentManager;
private final Context context;
class DraftsViewHolder extends RecyclerView.ViewHolder {
private TextView draftText;
private TextView repoInfo;
private TextView repoId;
private TextView draftId;
private TextView issueNumber;
private TextView issueType;
private TextView repoOwner;
private TextView repoName;
private TextView commentId;
private ImageView editCommentStatus;
private DraftWithRepository draftWithRepository;
private final TextView draftText;
private final TextView repoInfo;
private final ImageView editCommentStatus;
private DraftsViewHolder(View itemView) {
@ -50,21 +50,16 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
draftText = itemView.findViewById(R.id.draftText);
repoInfo = itemView.findViewById(R.id.repoInfo);
repoId = itemView.findViewById(R.id.repoId);
draftId = itemView.findViewById(R.id.draftId);
issueNumber = itemView.findViewById(R.id.issueNumber);
issueType = itemView.findViewById(R.id.issueType);
repoOwner = itemView.findViewById(R.id.repoOwner);
repoName = itemView.findViewById(R.id.repoName);
commentId = itemView.findViewById(R.id.commentId);
ImageView deleteDraft = itemView.findViewById(R.id.deleteDraft);
editCommentStatus = itemView.findViewById(R.id.editCommentStatus);
deleteDraft.setOnClickListener(itemDelete -> {
int getDraftId = Integer.parseInt(draftId.getText().toString());
int getDraftId = draftWithRepository.getDraftId();
deleteDraft(getAdapterPosition());
DraftsApi draftsApi = new DraftsApi(mCtx);
DraftsApi draftsApi = BaseApi.getInstance(context, DraftsApi.class);
assert draftsApi != null;
draftsApi.deleteSingleDraft(getDraftId);
});
@ -73,32 +68,34 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
Bundle bundle = new Bundle();
bundle.putString("commentBody", draftText.getText().toString());
bundle.putString("issueNumber", issueNumber.getText().toString());
bundle.putString("repositoryId", repoId.getText().toString());
bundle.putString("commentBody", draftWithRepository.getDraftText());
bundle.putString("issueNumber", String.valueOf(draftWithRepository.getIssueId()));
bundle.putString("repositoryId", String.valueOf(draftWithRepository.getRepositoryId()));
bundle.putString("draftTitle", repoInfo.getText().toString());
bundle.putString("commentId", commentId.getText().toString());
bundle.putString("draftId", draftId.getText().toString());
bundle.putString("commentId", draftWithRepository.getCommentId());
bundle.putString("draftId", String.valueOf(draftWithRepository.getDraftId()));
if(!commentId.getText().toString().isEmpty()) {
if(!draftWithRepository.getCommentId().isEmpty()) {
bundle.putString("commentAction", "edit");
}
TinyDB tinyDb = new TinyDB(mCtx);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putLong("repositoryId", Long.parseLong(repoId.getText().toString()));
//tinyDb.putString("issueType", issueType.getText().toString());
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("issueNumber", String.valueOf(draftWithRepository.getIssueId()));
tinyDb.putLong("repositoryId", draftWithRepository.getRepositoryId());
tinyDb.putString("issueType", draftWithRepository.getIssueType());
tinyDb.putString("repoFullName", draftWithRepository.getRepositoryOwner() + "/" + draftWithRepository.getRepositoryName());
BottomSheetReplyFragment bottomSheetReplyFragment = BottomSheetReplyFragment.newInstance(bundle);
bottomSheetReplyFragment.setOnInteractedListener(() -> context.startActivity(new Intent(context, IssueDetailActivity.class)));
bottomSheetReplyFragment.show(fragmentManager, "replyBottomSheet");
});
}
}
public DraftsAdapter(Context mCtx, FragmentManager fragmentManager, List<DraftWithRepository> draftsListMain) {
this.mCtx = mCtx;
public DraftsAdapter(Context ctx, FragmentManager fragmentManager, List<DraftWithRepository> draftsListMain) {
this.context = ctx;
this.fragmentManager = fragmentManager;
this.draftsList = draftsListMain;
}
@ -108,8 +105,7 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
draftsList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, draftsList.size());
Toasty.success(mCtx, mCtx.getResources().getString(R.string.draftsSingleDeleteSuccess));
Toasty.success(context, context.getResources().getString(R.string.draftsSingleDeleteSuccess));
}
@NonNull
@ -125,18 +121,14 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
DraftWithRepository currentItem = draftsList.get(position);
holder.repoId.setText(String.valueOf(currentItem.getRepositoryId()));
holder.draftId.setText(String.valueOf(currentItem.getDraftId()));
holder.issueNumber.setText(String.valueOf(currentItem.getIssueId()));
holder.issueType.setText(currentItem.getDraftType());
holder.repoOwner.setText(currentItem.getRepositoryOwner());
holder.repoName.setText(currentItem.getRepositoryName());
holder.draftText.setText(currentItem.getDraftText());
holder.commentId.setText(currentItem.getCommentId());
String issueNumber = "<font color='" + ResourcesCompat.getColor(context.getResources(), R.color.lightGray, null) + "'>" + context.getResources().getString(R.string.hash) + currentItem.getIssueId() + "</font>";
Spanned headTitle = HtmlCompat
.fromHtml(issueNumber + " " + currentItem.getRepositoryOwner() + " / " + currentItem.getRepositoryName(), HtmlCompat.FROM_HTML_MODE_LEGACY);
String issueNumber = "<font color='" + mCtx.getResources().getColor(R.color.lightGray) + "'>" + mCtx.getResources().getString(R.string.hash) + currentItem.getIssueId() + "</font>";
Spanned headTitle = Html.fromHtml(issueNumber + " " + currentItem.getRepositoryOwner() + " / " + currentItem.getRepositoryName());
holder.repoInfo.setText(headTitle);
holder.draftWithRepository = currentItem;
Markdown.render(context, currentItem.getDraftText(), holder.draftText);
if(!currentItem.getCommentId().equalsIgnoreCase("new")) {
holder.editCommentStatus.setVisibility(View.VISIBLE);
@ -144,7 +136,6 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
else {
holder.editCommentStatus.setVisibility(View.GONE);
}
}
@Override
@ -157,6 +148,4 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
draftsList = list;
notifyDataSetChanged();
}
}

View File

@ -0,0 +1,226 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.text.HtmlCompat;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.Issues;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
/**
* Author M M Arif
*/
public class ExploreIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private final int TYPE_LOAD = 0;
private List<Issues> searchedList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
private final TinyDB tinyDb;
public ExploreIssuesAdapter(List<Issues> dataList, Context ctx) {
this.context = ctx;
this.searchedList = dataList;
this.tinyDb = TinyDB.getInstance(context);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new ExploreIssuesAdapter.IssuesHolder(inflater.inflate(R.layout.list_issues, parent, false));
}
else {
return new ExploreIssuesAdapter.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) {
((ExploreIssuesAdapter.IssuesHolder) holder).bindData(searchedList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(searchedList.get(position).getTitle() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return searchedList.size();
}
class IssuesHolder extends RecyclerView.ViewHolder {
private Issues issue;
private final ImageView issueAssigneeAvatar;
private final TextView issueTitle;
private final TextView issueCreatedTime;
private final TextView issueCommentsCount;
IssuesHolder(View itemView) {
super(itemView);
issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
issueTitle = itemView.findViewById(R.id.issueTitle);
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
itemView.setOnClickListener(v -> {
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issue.getNumber());
intent.putExtra("openedFromLink", "true");
tinyDb.putString("issueNumber", String.valueOf(issue.getNumber()));
tinyDb.putString("issueType", "Issue");
tinyDb.putString("repoFullName", issue.getRepository().getFull_name());
String[] parts = issue.getRepository().getFull_name().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = BaseApi.getInstance(context, RepositoriesApi.class);
assert repositoryData != null;
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
context.startActivity(intent);
});
issueAssigneeAvatar.setOnClickListener(v -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", issue.getUser().getLogin());
context.startActivity(intent);
});
issueAssigneeAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, issue.getUser().getLogin(), context.getString(R.string.copyLoginIdToClipBoard, issue.getUser().getLogin()));
return true;
});
}
@SuppressLint("SetTextI18n")
void bindData(Issues issue) {
this.issue = issue;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
Locale locale = context.getResources().getConfiguration().locale;
String timeFormat = tinyDb.getString("dateFormat");
PicassoService.getInstance(context).get()
.load(issue.getUser().getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(imgRadius, 0))
.resize(120, 120)
.centerCrop()
.into(issueAssigneeAvatar);
String issueNumber_ = "<font color='" + ResourcesCompat.getColor(context.getResources(), R.color.lightGray, null) + "'>" + issue.getRepository().getFull_name() + context.getResources().getString(R.string.hash) + issue.getNumber() + "</font>";
issueTitle.setText(HtmlCompat.fromHtml(issueNumber_ + " " + issue.getTitle(), HtmlCompat.FROM_HTML_MODE_LEGACY));
issueCommentsCount.setText(String.valueOf(issue.getComments()));
switch(timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(locale);
String createdTime = prettyTime.format(issue.getCreated_at());
issueCreatedTime.setText(createdTime);
issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(issue.getCreated_at()), context));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", locale);
String createdTime = formatter.format(issue.getCreated_at());
issueCreatedTime.setText(createdTime);
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", locale);
String createdTime = formatter.format(issue.getCreated_at());
issueCreatedTime.setText(createdTime);
break;
}
}
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<Issues> list) {
searchedList = list;
notifyDataChanged();
}
}

View File

@ -0,0 +1,154 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.Organization;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OrganizationDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import java.util.List;
/**
* Author M M Arif
*/
public class ExplorePublicOrganizationsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private final int TYPE_LOAD = 0;
private List<Organization> organizationsList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public ExplorePublicOrganizationsAdapter(Context ctx, List<Organization> organizationsListMain) {
this.context = ctx;
this.organizationsList = organizationsListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new ExplorePublicOrganizationsAdapter.OrganizationsHolder(inflater.inflate(R.layout.list_organizations, parent, false));
}
else {
return new ExplorePublicOrganizationsAdapter.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) {
((ExplorePublicOrganizationsAdapter.OrganizationsHolder) holder).bindData(organizationsList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(organizationsList.get(position).getFull_name() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return organizationsList.size();
}
class OrganizationsHolder extends RecyclerView.ViewHolder {
private Organization organization;
private final ImageView image;
private final TextView orgName;
private final TextView orgDescription;
OrganizationsHolder(View itemView) {
super(itemView);
image = itemView.findViewById(R.id.imageAvatar);
orgName = itemView.findViewById(R.id.orgName);
orgDescription = itemView.findViewById(R.id.orgDescription);
itemView.setOnClickListener(v -> {
Context context = v.getContext();
Intent intent = new Intent(context, OrganizationDetailActivity.class);
intent.putExtra("orgName", organization.getUsername());
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("orgName", organization.getUsername());
tinyDb.putString("organizationId", String.valueOf(organization.getId()));
tinyDb.putBoolean("organizationAction", true);
context.startActivity(intent);
});
}
@SuppressLint("SetTextI18n")
void bindData(Organization organization) {
this.organization = organization;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
orgName.setText(organization.getUsername());
PicassoService.getInstance(context).get()
.load(organization.getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(imgRadius, 0))
.resize(120, 120)
.centerCrop()
.into(image);
if(!organization.getDescription().equals("")) {
orgDescription.setVisibility(View.VISIBLE);
orgDescription.setText(organization.getDescription());
}
else {
orgDescription.setVisibility(View.GONE);
}
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<Organization> list) {
organizationsList = list;
notifyDataChanged();
}
}

View File

@ -1,8 +1,6 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
@ -11,30 +9,31 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.gitnex.tea4j.models.UserRepositories;
import org.gitnex.tea4j.models.WatchInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.RepoForksActivity;
import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Objects;
import java.util.Locale;
import retrofit2.Call;
import retrofit2.Callback;
@ -42,285 +41,261 @@ import retrofit2.Callback;
* Author M M Arif
*/
public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepositoriesAdapter.ReposSearchViewHolder> {
public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<UserRepositories> searchedReposList;
private Context mCtx;
private final Context context;
private final int TYPE_LOAD = 0;
private List<UserRepositories> reposList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
private final TinyDB tinyDb;
public ExploreRepositoriesAdapter(List<UserRepositories> dataList, Context mCtx) {
this.mCtx = mCtx;
this.searchedReposList = dataList;
public ExploreRepositoriesAdapter(List<UserRepositories> dataList, Context ctx) {
this.context = ctx;
this.reposList = dataList;
this.tinyDb = TinyDB.getInstance(context);
}
static class ReposSearchViewHolder extends RecyclerView.ViewHolder {
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new ExploreRepositoriesAdapter.RepositoriesHolder(inflater.inflate(R.layout.list_repositories, parent, false));
}
else {
return new ExploreRepositoriesAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
private ImageView image;
private TextView repoName;
private TextView repoDescription;
private TextView fullName;
@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) {
((ExploreRepositoriesAdapter.RepositoriesHolder) holder).bindData(reposList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(reposList.get(position).getFullName() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return reposList.size();
}
class RepositoriesHolder extends RecyclerView.ViewHolder {
private UserRepositories userRepositories;
private final ImageView image;
private final TextView repoName;
private final TextView orgName;
private final TextView repoDescription;
private CheckBox isRepoAdmin;
private ImageView repoPrivatePublic;
private TextView repoStars;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private LinearLayout archiveRepo;
private TextView repoBranch;
private TextView htmlUrl;
private ReposSearchViewHolder(View itemView) {
private final TextView repoStars;
private final TextView repoLastUpdated;
private final View spacerView;
RepositoriesHolder(View itemView) {
super(itemView);
repoName = itemView.findViewById(R.id.repoName);
orgName = itemView.findViewById(R.id.orgName);
repoDescription = itemView.findViewById(R.id.repoDescription);
image = itemView.findViewById(R.id.imageAvatar);
fullName = itemView.findViewById(R.id.repoFullName);
isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin);
repoPrivatePublic = itemView.findViewById(R.id.imageRepoType);
image = itemView.findViewById(R.id.imageAvatar);
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);
repoType = itemView.findViewById(R.id.repoType);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
repoBranch = itemView.findViewById(R.id.repoBranch);
htmlUrl = itemView.findViewById(R.id.htmlUrl);
repoLastUpdated = itemView.findViewById(R.id.repoLastUpdated);
spacerView = itemView.findViewById(R.id.spacerView);
itemView.setOnClickListener(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());
intent.putExtra("repoFullName", userRepositories.getFullName());
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putString("repoFullName", userRepositories.getFullName());
tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
tinyDb.putString("repoBranch", repoBranch.getText().toString());
tinyDb.putString("repoBranch", userRepositories.getDefault_branch());
String[] parts = fullName.getText().toString().split("/");
if(userRepositories.getPrivateFlag()) {
tinyDb.putString("repoType", context.getResources().getString(R.string.strPrivate));
}
else {
tinyDb.putString("repoType", context.getResources().getString(R.string.strPublic));
}
String[] parts = userRepositories.getFullName().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context);
RepositoriesApi repositoryData = BaseApi.getInstance(context, RepositoriesApi.class);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
assert repositoryData != null;
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchInfo watch = new WatchInfo();
Call<WatchInfo> call;
call = RetrofitClient.getInstance(instanceUrl, context).getApiInterface().checkRepoWatchStatus(token, repoOwner, repoName);
call = RetrofitClient.getApiInterface(context).checkRepoWatchStatus(token, repoOwner, repoName);
call.enqueue(new Callback<WatchInfo>() {
@Override
public void onResponse(@NonNull Call<WatchInfo> call, @NonNull retrofit2.Response<WatchInfo> response) {
if(response.isSuccessful()) {
assert response.body() != null;
tinyDb.putBoolean("repoWatch", response.body().getSubscribed());
} else {
tinyDb.putBoolean("repoWatch", false);
if(response.code() != 404) {
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
}
else {
tinyDb.putBoolean("repoWatch", false);
if(response.code() != 404) {
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
}
}
@Override
public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) {
tinyDb.putBoolean("repoWatch", false);
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
});
}
context.startActivity(intent);
});
reposDropdownMenu.setOnClickListener(v -> {
final Context context = v.getContext();
@SuppressLint("InflateParams") View view = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_repository_in_list, null);
TextView repoOpenInBrowser = view.findViewById(R.id.repoOpenInBrowser);
TextView repoStargazers = view.findViewById(R.id.repoStargazers);
TextView repoWatchers = view.findViewById(R.id.repoWatchers);
TextView repoForksList = view.findViewById(R.id.repoForksList);
TextView repoCopyUrl = view.findViewById(R.id.repoCopyUrl);
TextView bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader);
bottomSheetHeader.setText(String.format("%s / %s", fullName.getText().toString().split("/")[0], fullName.getText().toString().split("/")[1]));
BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view);
dialog.show();
repoCopyUrl.setOnClickListener(openInBrowser -> {
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(context).getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("repoUrl", htmlUrl.getText().toString());
assert clipboard != null;
clipboard.setPrimaryClip(clip);
Toasty.info(context, context.getString(R.string.copyIssueUrlToastMsg));
dialog.dismiss();
});
repoOpenInBrowser.setOnClickListener(openInBrowser -> {
Intent intentOpenInBrowser = new Intent(context, OpenRepoInBrowserActivity.class);
intentOpenInBrowser.putExtra("repoFullNameBrowser", fullName.getText());
context.startActivity(intentOpenInBrowser);
dialog.dismiss();
});
repoStargazers.setOnClickListener(stargazers -> {
Intent intent = new Intent(context, RepoStargazersActivity.class);
intent.putExtra("repoFullNameForStars", fullName.getText());
context.startActivity(intent);
dialog.dismiss();
});
repoWatchers.setOnClickListener(watchers -> {
Intent intentW = new Intent(context, RepoWatchersActivity.class);
intentW.putExtra("repoFullNameForWatchers", fullName.getText());
context.startActivity(intentW);
dialog.dismiss();
});
repoForksList.setOnClickListener(forks -> {
Intent intentW = new Intent(context, RepoForksActivity.class);
intentW.putExtra("repoFullNameForForks", fullName.getText());
context.startActivity(intentW);
dialog.dismiss();
});
});
}
}
@SuppressLint("SetTextI18n")
void bindData(UserRepositories userRepositories) {
this.userRepositories = userRepositories;
@NonNull
@Override
public ExploreRepositoriesAdapter.ReposSearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
Locale locale = context.getResources().getConfiguration().locale;
String timeFormat = tinyDb.getString("dateFormat");
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_repositories, parent, false);
return new ExploreRepositoriesAdapter.ReposSearchViewHolder(v);
}
orgName.setText(userRepositories.getFullName().split("/")[0]);
repoName.setText(userRepositories.getFullName().split("/")[1]);
repoStars.setText(userRepositories.getStars_count());
@Override
public void onBindViewHolder(@NonNull final ExploreRepositoriesAdapter.ReposSearchViewHolder holder, int position) {
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(userRepositories.getName());
String firstCharacter = String.valueOf(userRepositories.getFullName().charAt(0));
UserRepositories currentItem = searchedReposList.get(position);
holder.repoDescription.setVisibility(View.GONE);
holder.repoBranch.setText(currentItem.getDefault_branch());
holder.htmlUrl.setText(currentItem.getHtml_url());
TextDrawable drawable = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT).fontSize(18).toUpperCase().width(28).height(28).endConfig().buildRoundRect(firstCharacter, color, 3);
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("")) {
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
if(userRepositories.getAvatar_url() != null) {
if(!userRepositories.getAvatar_url().equals("")) {
PicassoService.getInstance(context).get().load(userRepositories.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(image);
}
else {
image.setImageDrawable(drawable);
}
}
else {
holder.image.setImageDrawable(drawable);
image.setImageDrawable(drawable);
}
}
else {
holder.image.setImageDrawable(drawable);
}
holder.repoName.setText(currentItem.getName());
if(!currentItem.getDescription().equals("")) {
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublic.setVisibility(View.GONE);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count());
holder.repoOpenIssuesCount.setText(currentItem.getOpen_issues_count());
if(holder.isRepoAdmin == null) {
holder.isRepoAdmin = new CheckBox(mCtx);
}
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(userRepositories.getUpdated_at() != null) {
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
switch(timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(locale);
String createdTime = prettyTime.format(userRepositories.getUpdated_at());
repoLastUpdated.setText(context.getString(R.string.lastUpdatedAt, createdTime));
repoLastUpdated.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(userRepositories.getUpdated_at()), context));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", locale);
String createdTime = formatter.format(userRepositories.getUpdated_at());
repoLastUpdated.setText(context.getString(R.string.lastUpdatedAt, createdTime));
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", locale);
String createdTime = formatter.format(userRepositories.getUpdated_at());
repoLastUpdated.setText(context.getString(R.string.lastUpdatedAt, createdTime));
break;
}
}
}
else {
repoLastUpdated.setVisibility(View.GONE);
}
if(!userRepositories.getDescription().equals("")) {
repoDescription.setVisibility(View.VISIBLE);
repoDescription.setText(userRepositories.getDescription());
spacerView.setVisibility(View.GONE);
}
else {
repoDescription.setVisibility(View.GONE);
spacerView.setVisibility(View.VISIBLE);
}
if(isRepoAdmin == null) {
isRepoAdmin = new CheckBox(context);
}
isRepoAdmin.setChecked(userRepositories.getPermissions().isAdmin());
}
}
@Override
public int getItemCount() {
return searchedReposList.size();
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<UserRepositories> list) {
reposList = list;
notifyDataChanged();
}
}

View File

@ -0,0 +1,154 @@
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.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import java.util.List;
/**
* Author M M Arif
*/
public class ExploreUsersAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private final int TYPE_LOAD = 0;
private List<UserInfo> usersList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public ExploreUsersAdapter(Context ctx, List<UserInfo> usersListMain) {
this.context = ctx;
this.usersList = usersListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new ExploreUsersAdapter.UsersHolder(inflater.inflate(R.layout.list_explore_users, parent, false));
}
else {
return new ExploreUsersAdapter.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) {
((ExploreUsersAdapter.UsersHolder) holder).bindData(usersList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(usersList.get(position).getUsername() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return usersList.size();
}
class UsersHolder extends RecyclerView.ViewHolder {
private UserInfo userInfo;
private final ImageView userAvatar;
private final TextView userFullName;
private final TextView userName;
UsersHolder(View itemView) {
super(itemView);
userAvatar = itemView.findViewById(R.id.userAvatar);
userFullName = itemView.findViewById(R.id.userFullName);
userName = itemView.findViewById(R.id.userName);
itemView.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userInfo.getLogin());
context.startActivity(intent);
});
itemView.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userInfo.getLogin(), context.getString(R.string.copyLoginIdToClipBoard, userInfo.getLogin()));
return true;
});
}
@SuppressLint("SetTextI18n")
void bindData(UserInfo userInfo) {
this.userInfo = userInfo;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
userName.setText(userInfo.getUsername());
PicassoService.getInstance(context).get()
.load(userInfo.getAvatar())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(imgRadius, 0))
.resize(120, 120)
.centerCrop()
.into(userAvatar);
if(!userInfo.getFullname().equals("")) {
userFullName.setText(Html.fromHtml(userInfo.getFullname()));
userName.setText(context.getResources().getString(R.string.usernameWithAt, userInfo.getUsername()));
}
else {
userFullName.setText(userInfo.getUsername());
userName.setVisibility(View.GONE);
}
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<UserInfo> list) {
usersList = list;
notifyDataChanged();
}
}

View File

@ -7,13 +7,14 @@ 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.appcompat.content.res.AppCompatResources;
import androidx.recyclerview.widget.RecyclerView;
import org.apache.commons.io.FileUtils;
import org.gitnex.tea4j.models.Files;
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;
@ -23,55 +24,39 @@ import java.util.List;
public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHolder> implements Filterable {
private List<Files> filesList;
private Context mCtx;
private List<Files> filesListFull;
private final List<Files> originalFiles = new ArrayList<>();
private final List<Files> alteredFiles = new ArrayList<>();
private FilesAdapterListener filesListener;
private final Context context;
private final FilesAdapterListener filesListener;
public interface FilesAdapterListener {
void onClickDir(String str);
void onClickFile(String str);
void onClickFile(Files file);
}
class FilesViewHolder extends RecyclerView.ViewHolder {
class FilesViewHolder extends RecyclerView.ViewHolder {
private ImageView fileTypeImage;
private ImageView dirTypeImage;
private ImageView unknownTypeImage;
private TextView fileName;
private TextView fileType;
private TextView fileInfo;
private Files file;
private final ImageView fileTypeIs;
private final TextView fileName;
private final TextView fileInfo;
private FilesViewHolder(View itemView) {
super(itemView);
LinearLayout fileFrame = itemView.findViewById(R.id.fileFrame);
fileName = itemView.findViewById(R.id.fileName);
fileTypeImage = itemView.findViewById(R.id.fileImage);
dirTypeImage = itemView.findViewById(R.id.dirImage);
unknownTypeImage = itemView.findViewById(R.id.unknownImage);
fileType = itemView.findViewById(R.id.fileType);
fileTypeIs = itemView.findViewById(R.id.fileTypeIs);
fileInfo = itemView.findViewById(R.id.fileInfo);
fileFrame.setOnClickListener(v -> filesListener.onClickFile(file));
//ImageView filesDropdownMenu = itemView.findViewById(R.id.filesDropdownMenu);
fileName.setOnClickListener(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.warning(context, context.getString(R.string.filesGenericError));
}
});
/*filesDropdownMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -138,13 +123,24 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
}
}
public FilesAdapter(Context mCtx, List<Files> filesListMain, FilesAdapterListener filesListener) {
this.mCtx = mCtx;
this.filesList = filesListMain;
filesListFull = new ArrayList<>(filesList);
public FilesAdapter(Context ctx, FilesAdapterListener filesListener) {
this.context = ctx;
this.filesListener = filesListener;
}
public List<Files> getOriginalFiles() {
return originalFiles;
}
public void notifyOriginalDataSetChanged() {
alteredFiles.clear();
alteredFiles.addAll(originalFiles);
notifyDataSetChanged();
}
@NonNull
@Override
public FilesAdapter.FilesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@ -155,35 +151,43 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
@Override
public void onBindViewHolder(@NonNull FilesAdapter.FilesViewHolder holder, int position) {
Files currentItem = filesList.get(position);
Files currentItem = alteredFiles.get(position);
holder.fileType.setText(currentItem.getType());
holder.file = currentItem;
holder.fileName.setText(currentItem.getName());
if(currentItem.getType().equals("file")) {
holder.fileTypeImage.setVisibility(View.VISIBLE);
holder.dirTypeImage.setVisibility(View.GONE);
holder.unknownTypeImage.setVisibility(View.GONE);
holder.fileInfo.setVisibility(View.VISIBLE);
holder.fileInfo.setText(FileUtils.byteCountToDisplaySize(currentItem.getSize()));
}
else if(currentItem.getType().equals("dir")) {
holder.dirTypeImage.setVisibility(View.VISIBLE);
holder.unknownTypeImage.setVisibility(View.GONE);
holder.fileTypeImage.setVisibility(View.GONE);
holder.fileInfo.setVisibility(View.GONE);
}
else {
holder.unknownTypeImage.setVisibility(View.VISIBLE);
holder.dirTypeImage.setVisibility(View.GONE);
holder.fileTypeImage.setVisibility(View.GONE);
}
switch(currentItem.getType()) {
case "file":
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.ic_file));
holder.fileInfo.setVisibility(View.VISIBLE);
holder.fileInfo.setText(FileUtils.byteCountToDisplaySize(currentItem.getSize()));
break;
case "dir":
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.ic_directory));
holder.fileInfo.setVisibility(View.GONE);
break;
case "submodule":
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.ic_submodule));
holder.fileInfo.setVisibility(View.GONE);
break;
case "symlink":
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.ic_symlink));
holder.fileInfo.setVisibility(View.GONE);
break;
default:
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.ic_question));
}
}
@Override
public int getItemCount() {
return filesList.size();
return alteredFiles.size();
}
@Override
@ -191,17 +195,19 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
return filesFilter;
}
private Filter filesFilter = new Filter() {
private final Filter filesFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Files> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(filesListFull);
filteredList.addAll(originalFiles);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (Files item : filesListFull) {
for (Files item : originalFiles) {
if (item.getName().toLowerCase().contains(filterPattern) || item.getPath().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
@ -212,14 +218,19 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filesList.clear();
filesList.addAll((List) results.values);
alteredFiles.clear();
alteredFiles.addAll((List) results.values);
notifyDataSetChanged();
}
};
}

View File

@ -13,10 +13,11 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.fragment.app.FragmentManager;
import org.gitnex.tea4j.models.FileDiffView;
import org.mian.gitnex.R;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.helpers.DiffTextView;
import org.mian.gitnex.models.FileDiffView;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.views.DiffTextView;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
@ -36,9 +37,9 @@ public class FilesDiffAdapter extends BaseAdapter {
private static int COLOR_SELECTED;
private static int COLOR_FONT;
private Context context;
private FragmentManager fragmentManager;
private List<FileDiffView> fileDiffViews;
private final Context context;
private final FragmentManager fragmentManager;
private final List<FileDiffView> fileDiffViews;
public FilesDiffAdapter(Context context, FragmentManager fragmentManager, List<FileDiffView> fileDiffViews) {
@ -48,12 +49,11 @@ public class FilesDiffAdapter extends BaseAdapter {
selectedViews = new ConcurrentSkipListMap<>();
COLOR_ADDED = getColorFromAttribute(R.attr.diffAddedColor);
COLOR_REMOVED = getColorFromAttribute(R.attr.diffRemovedColor);
COLOR_NORMAL = getColorFromAttribute(R.attr.primaryBackgroundColor);
COLOR_SELECTED = getColorFromAttribute(R.attr.diffSelectedColor);
COLOR_FONT = getColorFromAttribute(R.attr.inputTextColor);
COLOR_ADDED = AppUtil.getColorFromAttribute(context, R.attr.diffAddedColor);
COLOR_REMOVED = AppUtil.getColorFromAttribute(context, R.attr.diffRemovedColor);
COLOR_NORMAL = AppUtil.getColorFromAttribute(context, R.attr.primaryBackgroundColor);
COLOR_SELECTED = AppUtil.getColorFromAttribute(context, R.attr.diffSelectedColor);
COLOR_FONT = AppUtil.getColorFromAttribute(context, R.attr.inputTextColor);
}
@Override
@ -93,7 +93,6 @@ public class FilesDiffAdapter extends BaseAdapter {
diffStats.setVisibility(View.GONE);
diffLines.addView(getMessageView(context.getResources().getString(R.string.binaryFileError)));
}
else {
@ -167,7 +166,6 @@ public class FilesDiffAdapter extends BaseAdapter {
}
diffTextView.setOnClickListener(v -> {
if(((DiffTextView) v).getCurrentBackgroundColor() != COLOR_SELECTED) {
@ -185,7 +183,6 @@ public class FilesDiffAdapter extends BaseAdapter {
});
diffTextView.setOnLongClickListener(v -> {
if(((DiffTextView) v).getCurrentBackgroundColor() == COLOR_SELECTED) {
@ -197,7 +194,6 @@ public class FilesDiffAdapter extends BaseAdapter {
stringBuilder.append(((DiffTextView) view).getText());
stringBuilder.append("\n");
}
stringBuilder.append("```\n\n");
@ -209,7 +205,6 @@ public class FilesDiffAdapter extends BaseAdapter {
bundle.putBoolean("cursorToEnd", true);
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
}
return true;
@ -226,7 +221,6 @@ public class FilesDiffAdapter extends BaseAdapter {
else {
diffLines.addView(getMessageView(context.getResources().getString(R.string.fileTooLarge)));
}
}
@ -248,22 +242,11 @@ public class FilesDiffAdapter extends BaseAdapter {
textView.setText(message);
return textView;
}
private String[] getLines(String content) {
return content.split("\\R");
}
private int getColorFromAttribute(int resid) {
TypedValue typedValue = new TypedValue();
context.getTheme().resolveAttribute(resid, typedValue, true);
return typedValue.data;
}
}

View File

@ -5,14 +5,14 @@ import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.text.Spanned;
import android.os.Handler;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
@ -20,38 +20,24 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.gson.JsonElement;
import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.IssueComments;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UserMentions;
import org.mian.gitnex.models.IssueComments;
import java.util.Collection;
import java.util.Collections;
import org.mian.gitnex.views.ReactionList;
import org.mian.gitnex.views.ReactionSpinner;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
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.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;
@ -61,132 +47,152 @@ import retrofit2.Callback;
public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdapter.IssueCommentViewHolder> {
private List<IssueComments> issuesComments;
private FragmentManager fragmentManager;
private Context mCtx;
private final Context context;
private final TinyDB tinyDB;
private final Bundle bundle;
private final List<IssueComments> issuesComments;
private final FragmentManager fragmentManager;
private final BottomSheetReplyFragment.OnInteractedListener onInteractedListener;
private final Locale locale;
public IssueCommentsAdapter(Context mCtx, FragmentManager fragmentManager, List<IssueComments> issuesCommentsMain) {
public IssueCommentsAdapter(Context ctx, Bundle bundle, List<IssueComments> issuesCommentsMain, FragmentManager fragmentManager, BottomSheetReplyFragment.OnInteractedListener onInteractedListener) {
this.mCtx = mCtx;
this.fragmentManager = fragmentManager;
this.context = ctx;
this.bundle = bundle;
this.issuesComments = issuesCommentsMain;
this.fragmentManager = fragmentManager;
this.onInteractedListener = onInteractedListener;
tinyDB = TinyDB.getInstance(ctx);
locale = ctx.getResources().getConfiguration().locale;
}
class IssueCommentViewHolder extends RecyclerView.ViewHolder {
private TextView issueNumber;
private TextView commendId;
private ImageView issueCommenterAvatar;
private TextView issueComment;
private TextView issueCommentDate;
private TextView commendBodyRaw;
private TextView commentModified;
private TextView commenterUsername;
private TextView htmlUrl;
private String userLoginId;
private IssueComments issueComment;
private IssueCommentViewHolder(View itemView) {
private final ImageView avatar;
private final TextView author;
private final TextView information;
private final TextView comment;
private final LinearLayout commentReactionBadges;
super(itemView);
private IssueCommentViewHolder(View view) {
issueNumber = itemView.findViewById(R.id.issueNumber);
commendId = itemView.findViewById(R.id.commendId);
issueCommenterAvatar = itemView.findViewById(R.id.issueCommenterAvatar);
issueComment = itemView.findViewById(R.id.issueComment);
issueCommentDate = itemView.findViewById(R.id.issueCommentDate);
ImageView commentsOptionsMenu = itemView.findViewById(R.id.commentsOptionsMenu);
commendBodyRaw = itemView.findViewById(R.id.commendBodyRaw);
commentModified = itemView.findViewById(R.id.commentModified);
commenterUsername = itemView.findViewById(R.id.commenterUsername);
htmlUrl = itemView.findViewById(R.id.htmlUrl);
super(view);
commentsOptionsMenu.setOnClickListener(v -> {
avatar = view.findViewById(R.id.avatar);
author = view.findViewById(R.id.author);
information = view.findViewById(R.id.information);
ImageView menu = view.findViewById(R.id.menu);
comment = view.findViewById(R.id.comment);
commentReactionBadges = view.findViewById(R.id.commentReactionBadges);
final Context ctx = v.getContext();
final TinyDB tinyDb = new TinyDB(ctx);
final String loginUid = tinyDb.getString("loginUid");
menu.setOnClickListener(v -> {
@SuppressLint("InflateParams") View view = LayoutInflater.from(ctx).inflate(R.layout.bottom_sheet_issue_comments, null);
final String loginUid = tinyDB.getString("loginUid");
TextView commentMenuEdit = view.findViewById(R.id.commentMenuEdit);
TextView commentShare = view.findViewById(R.id.issueCommentShare);
TextView commentMenuQuote = view.findViewById(R.id.commentMenuQuote);
TextView commentMenuCopy = view.findViewById(R.id.commentMenuCopy);
TextView commentMenuDelete = view.findViewById(R.id.commentMenuDelete);
TextView issueCommentCopyUrl = view.findViewById(R.id.issueCommentCopyUrl);
@SuppressLint("InflateParams") View vw = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_issue_comments, null);
if(!loginUid.contentEquals(commenterUsername.getText())) {
TextView commentMenuEdit = vw.findViewById(R.id.commentMenuEdit);
TextView commentShare = vw.findViewById(R.id.issueCommentShare);
TextView commentMenuQuote = vw.findViewById(R.id.commentMenuQuote);
TextView commentMenuCopy = vw.findViewById(R.id.commentMenuCopy);
TextView commentMenuDelete = vw.findViewById(R.id.commentMenuDelete);
TextView issueCommentCopyUrl = vw.findViewById(R.id.issueCommentCopyUrl);
if(!loginUid.contentEquals(issueComment.getUser().getUsername())) {
commentMenuEdit.setVisibility(View.GONE);
commentMenuDelete.setVisibility(View.GONE);
}
if(issueComment.getText().toString().isEmpty()) {
if(issueComment.getBody().isEmpty()) {
commentMenuCopy.setVisibility(View.GONE);
}
BottomSheetDialog dialog = new BottomSheetDialog(ctx);
dialog.setContentView(view);
BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(vw);
dialog.show();
commentMenuEdit.setOnClickListener(ediComment -> {
LinearLayout linearLayout = vw.findViewById(R.id.commentReactionButtons);
TextView loadReactions = new TextView(context);
loadReactions.setText(context.getString(R.string.genericWaitFor));
loadReactions.setGravity(Gravity.CENTER);
loadReactions.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 160));
linearLayout.addView(loadReactions);
Bundle bundle = new Bundle();
bundle.putString("commentId", commendId.getText().toString());
bundle.putString("commentAction", "edit");
bundle.putString("commentBody", commendBodyRaw.getText().toString());
Bundle bundle1 = new Bundle();
bundle1.putAll(bundle);
bundle1.putInt("commentId", issueComment.getId());
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
ReactionSpinner reactionSpinner = new ReactionSpinner(context, bundle1);
reactionSpinner.setOnInteractedListener(() -> {
tinyDB.putBoolean("commentEdited", true);
onInteractedListener.onInteracted();
dialog.dismiss();
});
commentShare.setOnClickListener(ediComment -> {
Handler handler = new Handler();
handler.postDelayed(() -> {
linearLayout.removeView(loadReactions);
reactionSpinner.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 160));
linearLayout.addView(reactionSpinner);
}, 2500);
commentMenuEdit.setOnClickListener(v1 -> {
Bundle bundle = new Bundle();
bundle.putInt("commentId", issueComment.getId());
bundle.putString("commentAction", "edit");
bundle.putString("commentBody", issueComment.getBody());
BottomSheetReplyFragment bottomSheetReplyFragment = BottomSheetReplyFragment.newInstance(bundle);
bottomSheetReplyFragment.setOnInteractedListener(onInteractedListener);
bottomSheetReplyFragment.show(fragmentManager, "replyBottomSheet");
dialog.dismiss();
});
commentShare.setOnClickListener(v1 -> {
// get comment Url
CharSequence commentUrl = htmlUrl.getText();
CharSequence commentUrl = issueComment.getHtml_url();
// share issue comment
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
String intentHeader = tinyDb.getString("issueNumber") + ctx.getResources().getString(R.string.hash) + "issuecomment-" + commendId.getText() + " " + tinyDb.getString("issueTitle");
String intentHeader = tinyDB.getString("issueNumber") + context.getResources().getString(R.string.hash) + "issuecomment-" + issueComment.getId() + " " + tinyDB.getString("issueTitle");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, intentHeader);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, commentUrl);
ctx.startActivity(Intent.createChooser(sharingIntent, intentHeader));
context.startActivity(Intent.createChooser(sharingIntent, intentHeader));
dialog.dismiss();
});
issueCommentCopyUrl.setOnClickListener(ediComment -> {
issueCommentCopyUrl.setOnClickListener(v1 -> {
// comment Url
CharSequence commentUrl = htmlUrl.getText();
CharSequence commentUrl = issueComment.getHtml_url();
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(context).getSystemService(Context.CLIPBOARD_SERVICE);
assert clipboard != null;
ClipData clip = ClipData.newPlainText(commentUrl, commentUrl);
clipboard.setPrimaryClip(clip);
dialog.dismiss();
Toasty.success(ctx, ctx.getString(R.string.copyIssueUrlToastMsg));
Toasty.success(context, context.getString(R.string.copyIssueUrlToastMsg));
});
commentMenuQuote.setOnClickListener(v1 -> {
StringBuilder stringBuilder = new StringBuilder();
String commenterName = commenterUsername.getText().toString();
if(!commenterName.equals(tinyDb.getString("userLogin"))) {
String commenterName = issueComment.getUser().getUsername();
if(!commenterName.equals(tinyDB.getString("userLogin"))) {
stringBuilder.append("@").append(commenterName).append("\n\n");
}
String[] lines = commendBodyRaw.getText().toString().split("\\R");
String[] lines = issueComment.getBody().split("\\R");
for(String line : lines) {
stringBuilder.append(">").append(line).append("\n");
}
@ -198,33 +204,37 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
dialog.dismiss();
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
});
commentMenuCopy.setOnClickListener(view1 -> {
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
commentMenuCopy.setOnClickListener(v1 -> {
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(context).getSystemService(Context.CLIPBOARD_SERVICE);
assert clipboard != null;
ClipData clip = ClipData.newPlainText("Comment on issue #" + issueNumber.getText().toString(), issueComment.getText().toString());
ClipData clip = ClipData.newPlainText("Comment on issue #" + tinyDB.getString("issueNumber"), issueComment.getBody());
clipboard.setPrimaryClip(clip);
dialog.dismiss();
Toasty.success(ctx, ctx.getString(R.string.copyIssueCommentToastMsg));
Toasty.success(context, context.getString(R.string.copyIssueCommentToastMsg));
});
commentMenuDelete.setOnClickListener(deleteComment -> {
deleteIssueComment(ctx, Integer.parseInt(commendId.getText().toString()), getAdapterPosition());
commentMenuDelete.setOnClickListener(v1 -> {
deleteIssueComment(context, issueComment.getId(), getAdapterPosition());
dialog.dismiss();
});
});
}
avatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userLoginId);
context.startActivity(intent);
});
avatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
return true;
});
}
}
private void updateAdapter(int position) {
@ -232,27 +242,23 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
issuesComments.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, issuesComments.size());
}
private void deleteIssueComment(final Context ctx, final int commentId, int position) {
final TinyDB tinyDb = new TinyDB(ctx);
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").split("/");
final String loginUid = tinyDB.getString("loginUid");
final String instanceToken = "token " + tinyDB.getString(loginUid + "-token");
String[] repoFullName = tinyDB.getString("repoFullName").split("/");
if (repoFullName.length != 2) {
return;
}
final String repoOwner = repoFullName[0];
final String repoName = repoFullName[1];
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
Call<JsonElement> call = RetrofitClient
.getApiInterface(ctx)
.deleteComment(instanceToken, repoOwner, repoName, commentId);
call.enqueue(new Callback<JsonElement>() {
@ -260,47 +266,40 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 204) {
switch(response.code()) {
updateAdapter(position);
Toasty.success(ctx, ctx.getResources().getString(R.string.deleteCommentSuccess));
case 204:
updateAdapter(position);
Toasty.success(ctx, ctx.getResources().getString(R.string.deleteCommentSuccess));
break;
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle),
case 401:
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle),
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
break;
case 404:
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
break;
default:
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
else if(response.code() == 403) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
}
@NonNull
@ -309,111 +308,68 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_issue_comments, parent, false);
return new IssueCommentsAdapter.IssueCommentViewHolder(v);
}
@SuppressLint("SetTextI18n")
@Override
public void onBindViewHolder(@NonNull IssueCommentsAdapter.IssueCommentViewHolder holder, int position) {
final TinyDB tinyDb = new TinyDB(mCtx);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
String timeFormat = tinyDB.getString("dateFormat");
IssueComments issueComment = issuesComments.get(position);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
IssueComments currentItem = issuesComments.get(position);
holder.userLoginId = issueComment.getUser().getLogin();
holder.htmlUrl.setText(currentItem.getHtml_url());
holder.commenterUsername.setText(currentItem.getUser().getUsername());
holder.commendId.setText(String.valueOf(currentItem.getId()));
holder.commendBodyRaw.setText(currentItem.getBody());
holder.issueComment = issueComment;
holder.author.setText(issueComment.getUser().getUsername());
if(!currentItem.getUser().getFull_name().equals("")) {
holder.issueCommenterAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCommenter) + currentItem.getUser().getFull_name(), mCtx));
}
else {
holder.issueCommenterAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCommenter) + currentItem.getUser().getLogin(), mCtx));
}
PicassoService.getInstance(context).get()
.load(issueComment.getUser().getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(imgRadius, 0))
.resize(AppUtil.getPixelsFromDensity(context, 35), AppUtil.getPixelsFromDensity(context, 35))
.centerCrop()
.into(holder.avatar);
PicassoService.getInstance(mCtx).get().load(currentItem.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.issueCommenterAvatar);
Markdown.render(context, EmojiParser.parseToUnicode(issueComment.getBody()), holder.comment);
String cleanIssueComments = currentItem.getBody().trim();
final Markwon markwon = Markwon.builder(Objects.requireNonNull(mCtx)).usePlugin(CorePlugin.create()).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(drawable -> 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());
StringBuilder informationBuilder = null;
if(issueComment.getCreated_at() != null) {
if(timeFormat.equals("pretty")) {
informationBuilder = new StringBuilder(TimeHelper.formatTime(issueComment.getCreated_at(), locale, "pretty", context));
holder.information.setOnClickListener(v -> TimeHelper.customDateFormatForToastDateFormat(issueComment.getCreated_at()));
}
})).usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder.codeTextColor(tinyDb.getInt("codeBlockColor")).codeBackgroundColor(tinyDb.getInt("codeBlockBackground")).linkColor(mCtx.getResources().getColor(R.color.lightBlue));
else if(timeFormat.equals("normal")) {
informationBuilder = new StringBuilder(TimeHelper.formatTime(issueComment.getCreated_at(), locale, "normal", context));
}
}).usePlugin(TablePlugin.create(mCtx)).usePlugin(TaskListPlugin.create(mCtx)).usePlugin(HtmlPlugin.create()).usePlugin(StrikethroughPlugin.create()).usePlugin(LinkifyPlugin.create()).build();
Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueComments));
markwon.setParsedMarkdown(holder.issueComment, UserMentions.UserMentionsFunc(mCtx, bodyWithMD, cleanIssueComments));
String edited;
if(!currentItem.getUpdated_at().equals(currentItem.getCreated_at())) {
edited = mCtx.getResources().getString(R.string.colorfulBulletSpan) + mCtx.getResources().getString(R.string.modifiedText);
holder.commentModified.setVisibility(View.VISIBLE);
holder.commentModified.setText(edited);
holder.commentModified.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getUpdated_at()), mCtx));
}
else {
holder.commentModified.setVisibility(View.INVISIBLE);
if(!issueComment.getCreated_at().equals(issueComment.getUpdated_at())) {
if(informationBuilder != null) {
informationBuilder.append(context.getString(R.string.colorfulBulletSpan)).append(context.getString(R.string.modifiedText));
}
}
}
holder.issueCommentDate.setText(TimeHelper.formatTime(currentItem.getCreated_at(), new Locale(locale), timeFormat, mCtx));
holder.information.setText(informationBuilder);
Bundle bundle1 = new Bundle();
bundle1.putAll(bundle);
bundle1.putInt("commentId", issueComment.getId());
ReactionList reactionList = new ReactionList(context, bundle1);
holder.commentReactionBadges.addView(reactionList);
reactionList.setOnReactionAddedListener(() -> {
if(holder.commentReactionBadges.getVisibility() != View.VISIBLE) {
holder.commentReactionBadges.post(() -> holder.commentReactionBadges.setVisibility(View.VISIBLE));
}
});
if(timeFormat.equals("pretty")) {
holder.issueCommentDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getCreated_at()), mCtx));
}
}
@Override
public int getItemCount() {
return issuesComments.size();
}
}

View File

@ -3,23 +3,26 @@ 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.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.text.HtmlCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.Issues;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Issues;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@ -32,17 +35,16 @@ import java.util.Locale;
public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private final Context context;
private final int TYPE_LOAD = 0;
private List<Issues> issuesList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public IssuesAdapter(Context context, List<Issues> issuesListMain) {
public IssuesAdapter(Context ctx, List<Issues> issuesListMain) {
this.context = context;
this.context = ctx;
this.issuesList = issuesListMain;
}
@NonNull
@ -57,7 +59,6 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
else {
return new LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
@Override
@ -67,15 +68,12 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((IssuesHolder) holder).bindData(issuesList.get(position));
}
}
@Override
@ -87,104 +85,94 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
else {
return 1;
}
}
@Override
public int getItemCount() {
return issuesList.size();
}
class IssuesHolder extends RecyclerView.ViewHolder {
private TextView issueNumber;
private ImageView issueAssigneeAvatar;
private TextView issueTitle;
private TextView issueCreatedTime;
private TextView issueCommentsCount;
private Issues issue;
private final ImageView issueAssigneeAvatar;
private final TextView issueTitle;
private final TextView issueCreatedTime;
private final TextView issueCommentsCount;
IssuesHolder(View itemView) {
super(itemView);
issueNumber = itemView.findViewById(R.id.issueNumber);
issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
issueTitle = itemView.findViewById(R.id.issueTitle);
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount);
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
issueTitle.setOnClickListener(v -> {
Context context = v.getContext();
itemView.setOnClickListener(layoutView -> {
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText());
intent.putExtra("issueNumber", issue.getNumber());
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("issueNumber", String.valueOf(issue.getNumber()));
tinyDb.putString("issueType", "Issue");
context.startActivity(intent);
});
frameCommentsCount.setOnClickListener(v -> {
Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText());
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "Issue");
issueAssigneeAvatar.setOnClickListener(v -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", issue.getUser().getLogin());
context.startActivity(intent);
});
issueAssigneeAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, issue.getUser().getLogin(), context.getString(R.string.copyLoginIdToClipBoard, issue.getUser().getLogin()));
return true;
});
}
@SuppressLint("SetTextI18n")
void bindData(Issues issuesModel) {
void bindData(Issues issue) {
final TinyDB tinyDb = new TinyDB(context);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
TinyDB tinyDb = TinyDB.getInstance(context);
Locale locale = context.getResources().getConfiguration().locale;
String timeFormat = tinyDb.getString("dateFormat");
if(!issuesModel.getUser().getFull_name().equals("")) {
issueAssigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueCreator) + issuesModel.getUser().getFull_name(), context));
}
else {
issueAssigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueCreator) + issuesModel.getUser().getLogin(), context));
}
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
PicassoService.getInstance(context).get().load(issuesModel.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar);
PicassoService.getInstance(context).get()
.load(issue.getUser().getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(imgRadius, 0))
.resize(120, 120)
.centerCrop()
.into(issueAssigneeAvatar);
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()));
String issueNumber_ = "<font color='" + ResourcesCompat.getColor(context.getResources(), R.color.lightGray, null) + "'>" + context.getResources().getString(R.string.hash) + issue.getNumber() + "</font>";
issueTitle.setText(HtmlCompat.fromHtml(issueNumber_ + " " + EmojiParser.parseToUnicode(issue.getTitle()), HtmlCompat.FROM_HTML_MODE_LEGACY));
issueNumber.setText(String.valueOf(issuesModel.getNumber()));
issueCommentsCount.setText(String.valueOf(issuesModel.getComments()));
this.issue = issue;
this.issueCommentsCount.setText(String.valueOf(issue.getComments()));
switch(timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(issuesModel.getCreated_at()), context));
PrettyTime prettyTime = new PrettyTime(locale);
String createdTime = prettyTime.format(issue.getCreated_at());
this.issueCreatedTime.setText(createdTime);
this.issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(issue.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(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", locale);
String createdTime = formatter.format(issue.getCreated_at());
this.issueCreatedTime.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(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", locale);
String createdTime = formatter.format(issue.getCreated_at());
this.issueCreatedTime.setText(createdTime);
break;
}
}
@ -199,32 +187,27 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<Issues> list) {

View File

@ -15,12 +15,11 @@ import androidx.cardview.widget.CardView;
import androidx.core.widget.ImageViewCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.gitnex.tea4j.models.Labels;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.CreateLabelActivity;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.models.Labels;
import java.util.ArrayList;
import java.util.List;
/**
@ -29,19 +28,17 @@ import java.util.List;
public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsViewHolder> {
private List<Labels> labelsList;
final private Context mCtx;
private ArrayList<Integer> labelsArray = new ArrayList<>();
private final List<Labels> labelsList;
private static String type;
private static String orgName;
static class LabelsViewHolder extends RecyclerView.ViewHolder {
private TextView labelTitle;
private TextView labelId;
private TextView labelColor;
private Labels labels;
private CardView labelView;
private ImageView labelIcon;
private TextView labelName;
private final CardView labelView;
private final ImageView labelIcon;
private final TextView labelName;
private LabelsViewHolder(View itemView) {
super(itemView);
@ -50,9 +47,6 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
labelIcon = itemView.findViewById(R.id.labelIcon);
labelName = itemView.findViewById(R.id.labelName);
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);
labelsOptionsMenu.setOnClickListener(v -> {
@ -65,7 +59,7 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
TextView labelMenuDelete = view.findViewById(R.id.labelMenuDelete);
TextView bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader);
bottomSheetHeader.setText(labelTitle.getText());
bottomSheetHeader.setText(labels.getName());
BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view);
dialog.show();
@ -73,24 +67,25 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
labelMenuEdit.setOnClickListener(editLabel -> {
Intent intent = new Intent(context, CreateLabelActivity.class);
intent.putExtra("labelId", labelId.getText());
intent.putExtra("labelTitle", labelTitle.getText());
intent.putExtra("labelColor", labelColor.getText());
intent.putExtra("labelId", String.valueOf(labels.getId()));
intent.putExtra("labelTitle", labels.getName());
intent.putExtra("labelColor", labels.getColor());
intent.putExtra("labelAction", "edit");
intent.putExtra("type", type);
intent.putExtra("orgName", orgName);
context.startActivity(intent);
dialog.dismiss();
});
labelMenuDelete.setOnClickListener(deleteLabel -> {
AlertDialogs.labelDeleteDialog(context, labelTitle.getText().toString(), labelId.getText().toString(),
AlertDialogs.labelDeleteDialog(context, labels.getName(), String.valueOf(labels.getId()),
context.getResources().getString(R.string.labelDeleteTitle),
context.getResources().getString(R.string.labelDeleteMessage),
context.getResources().getString(R.string.labelDeletePositiveButton),
context.getResources().getString(R.string.labelDeleteNegativeButton));
context.getResources().getString(R.string.labelDeleteTitle),
context.getResources().getString(R.string.labelDeleteNegativeButton),
type, orgName);
dialog.dismiss();
});
});
@ -98,9 +93,11 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
}
}
public LabelsAdapter(Context mCtx, List<Labels> labelsMain) {
this.mCtx = mCtx;
this.labelsList = labelsMain;
public LabelsAdapter(Context ctx, List<Labels> labelsMain, String type, String orgName) {
this.labelsList = labelsMain;
LabelsAdapter.type = type;
LabelsAdapter.orgName = orgName;
}
@NonNull
@ -114,10 +111,7 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
public void onBindViewHolder(@NonNull LabelsAdapter.LabelsViewHolder holder, int position) {
Labels currentItem = labelsList.get(position);
holder.labelTitle.setText(currentItem.getName());
holder.labelId.setText(String.valueOf(currentItem.getId()));
holder.labelColor.setText(currentItem.getColor());
holder.labels = currentItem;
String labelColor = currentItem.getColor();
String labelName = currentItem.getName();
@ -130,7 +124,6 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
holder.labelName.setTextColor(contrastColor);
holder.labelName.setText(labelName);
holder.labelView.setCardBackgroundColor(color);
}
@Override

View File

@ -9,8 +9,8 @@ import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.Labels;
import org.mian.gitnex.R;
import org.mian.gitnex.models.Labels;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
@ -22,11 +22,11 @@ import java.util.List;
public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.LabelsViewHolder> {
private List<Integer> currentLabelsIds;
private List<Labels> labels;
private List<String> labelsStrings = new ArrayList<>();
private final List<Labels> labels;
private final List<String> labelsStrings = new ArrayList<>();
private List<Integer> labelsIds = new ArrayList<>();
private LabelsListAdapterListener labelsListener;
private final LabelsListAdapterListener labelsListener;
public interface LabelsListAdapterListener {
@ -43,17 +43,18 @@ public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.La
static class LabelsViewHolder extends RecyclerView.ViewHolder {
private CheckBox labelSelection;
private TextView labelText;
private ImageView labelColor;
private final CheckBox labelSelection;
private final TextView labelText;
private final ImageView labelColor;
private LabelsViewHolder(View itemView) {
super(itemView);
this.setIsRecyclable(false);
labelSelection = itemView.findViewById(R.id.labelSelection);
labelText = itemView.findViewById(R.id.labelText);
labelColor = itemView.findViewById(R.id.labelColor);
}
}
@ -85,6 +86,7 @@ public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.La
}
currentLabelsIds = new ArrayList<>(new LinkedHashSet<>(currentLabelsIds));
for(int i = 0; i < currentLabelsIds.size(); i++) {
if(currentLabelsIds.contains(currentItem.getId())) {
@ -93,6 +95,7 @@ public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.La
labelsIds.add(currentLabelsIds.get(i));
}
}
labelsListener.labelsIdsInterface(labelsIds);
holder.labelSelection.setOnCheckedChangeListener((buttonView, isChecked) -> {
@ -117,6 +120,7 @@ public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.La
@Override
public int getItemCount() {
return labels.size();
}

View File

@ -2,6 +2,8 @@ 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;
@ -10,10 +12,12 @@ import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo;
import java.util.ArrayList;
import java.util.List;
@ -23,26 +27,40 @@ import java.util.List;
public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
private List<UserInfo> membersList;
private Context mCtx;
private List<UserInfo> membersListFull;
private final List<UserInfo> membersList;
private final Context context;
private final List<UserInfo> membersListFull;
private class ViewHolder {
private ImageView memberAvatar;
private TextView memberName;
private String userLoginId;
private final ImageView memberAvatar;
private final TextView memberName;
ViewHolder(View v) {
memberAvatar = v.findViewById(R.id.memberAvatar);
memberName = v.findViewById(R.id.memberName);
memberAvatar.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userLoginId);
context.startActivity(intent);
});
memberAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
return true;
});
}
}
public MembersByOrgAdapter(Context mCtx, List<UserInfo> membersListMain) {
this.mCtx = mCtx;
public MembersByOrgAdapter(Context ctx, List<UserInfo> membersListMain) {
this.context = ctx;
this.membersList = membersListMain;
membersListFull = new ArrayList<>(membersList);
}
@Override
@ -67,31 +85,37 @@ public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
MembersByOrgAdapter.ViewHolder viewHolder = null;
if (finalView == null) {
finalView = LayoutInflater.from(mCtx).inflate(R.layout.list_members_by_org, null);
viewHolder = new MembersByOrgAdapter.ViewHolder(finalView);
finalView = LayoutInflater.from(context).inflate(R.layout.list_members_by_org, null);
viewHolder = new ViewHolder(finalView);
finalView.setTag(viewHolder);
}
else {
viewHolder = (MembersByOrgAdapter.ViewHolder) finalView.getTag();
}
initData(viewHolder, position);
return finalView;
}
private void initData(MembersByOrgAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = membersList.get(position);
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(viewHolder.memberAvatar);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
PicassoService.getInstance(context).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(viewHolder.memberAvatar);
viewHolder.userLoginId = currentItem.getLogin();
if(!currentItem.getFullname().equals("")) {
viewHolder.memberName.setText(currentItem.getFullname());
viewHolder.memberName.setText(Html.fromHtml(currentItem.getFullname()));
}
else {
viewHolder.memberName.setText(currentItem.getLogin());
}
}
@Override
@ -99,14 +123,17 @@ public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
return membersFilter;
}
private Filter membersFilter = new Filter() {
private final Filter membersFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<UserInfo> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(membersListFull);
} else {
}
else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (UserInfo item : membersListFull) {
@ -124,6 +151,7 @@ public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
membersList.clear();
membersList.addAll((List) results.values);
notifyDataSetChanged();

View File

@ -2,9 +2,6 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Spanned;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@ -13,40 +10,24 @@ import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.Milestones;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.MilestoneActions;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Milestones;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
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 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.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
@ -54,19 +35,17 @@ import io.noties.markwon.linkify.LinkifyPlugin;
public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private final Context context;
private final int TYPE_LOAD = 0;
private List<Milestones> dataList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false;
private boolean isMoreDataAvailable = true;
private String TAG = StaticGlobalVariables.tagMilestonesAdapter;
public MilestonesAdapter(Context context, List<Milestones> dataListMain) {
public MilestonesAdapter(Context ctx, List<Milestones> dataListMain) {
this.context = context;
this.context = ctx;
this.dataList = dataListMain;
}
@NonNull
@ -81,7 +60,6 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
else {
return new MilestonesAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
@Override
@ -91,33 +69,29 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((MilestonesAdapter.DataHolder) holder).bindData(dataList.get(position));
}
}
class DataHolder extends RecyclerView.ViewHolder {
private TextView milestoneId;
private TextView msTitle;
private TextView msDescription;
private TextView msOpenIssues;
private TextView msClosedIssues;
private TextView msDueDate;
private ProgressBar msProgress;
private TextView milestoneStatus;
private Milestones milestones;
private final TextView msTitle;
private final TextView msDescription;
private final TextView msOpenIssues;
private final TextView msClosedIssues;
private final TextView msDueDate;
private final ProgressBar msProgress;
DataHolder(View itemView) {
super(itemView);
milestoneId = itemView.findViewById(R.id.milestoneId);
msTitle = itemView.findViewById(R.id.milestoneTitle);
msDescription = itemView.findViewById(R.id.milestoneDescription);
msOpenIssues = itemView.findViewById(R.id.milestoneIssuesOpen);
@ -125,12 +99,11 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
msDueDate = itemView.findViewById(R.id.milestoneDueDate);
msProgress = itemView.findViewById(R.id.milestoneProgress);
ImageView milestonesMenu = itemView.findViewById(R.id.milestonesMenu);
milestoneStatus = itemView.findViewById(R.id.milestoneStatus);
milestonesMenu.setOnClickListener(v -> {
Context ctx = v.getContext();
int milestoneId_ = Integer.parseInt(milestoneId.getText().toString());
int milestoneId_ = Integer.parseInt(String.valueOf(milestones.getId()));
@SuppressLint("InflateParams") View view = LayoutInflater.from(ctx).inflate(R.layout.bottom_sheet_milestones_in_list, null);
@ -141,17 +114,15 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
dialog.setContentView(view);
dialog.show();
if(milestoneStatus.getText().toString().equals("open")) {
if(milestones.getState().equals("open")) {
closeMilestone.setVisibility(View.VISIBLE);
openMilestone.setVisibility(View.GONE);
}
else {
closeMilestone.setVisibility(View.GONE);
openMilestone.setVisibility(View.VISIBLE);
}
closeMilestone.setOnClickListener(v12 -> {
@ -159,7 +130,6 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
MilestoneActions.closeMilestone(ctx, milestoneId_);
dialog.dismiss();
updateAdapter(getAdapterPosition());
});
openMilestone.setOnClickListener(v12 -> {
@ -167,7 +137,6 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
MilestoneActions.openMilestone(ctx, milestoneId_);
dialog.dismiss();
updateAdapter(getAdapterPosition());
});
});
@ -177,71 +146,16 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
@SuppressLint("SetTextI18n")
void bindData(Milestones dataModel) {
final TinyDB tinyDb = new TinyDB(context);
final String locale = tinyDb.getString("locale");
this.milestones = dataModel;
final TinyDB tinyDb = TinyDB.getInstance(context);
final String locale = context.getResources().getConfiguration().locale.getLanguage();
final String timeFormat = tinyDb.getString("dateFormat");
milestoneId.setText(String.valueOf(dataModel.getId()));
milestoneStatus.setText(dataModel.getState());
Markwon markwon = Markwon.builder(Objects.requireNonNull(context)).usePlugin(CorePlugin.create()).usePlugin(ImagesPlugin.create(plugin -> {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = context.getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
context.getPackageName());
final Drawable drawable = context.getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(drawable -> null);
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(context.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(context.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(context.getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(context))
.usePlugin(TaskListPlugin.create(context))
.usePlugin(HtmlPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
Spanned msTitle_ = markwon.toMarkdown(dataModel.getTitle());
markwon.setParsedMarkdown(msTitle, msTitle_);
Markdown.render(context, dataModel.getTitle(), msTitle);
if(!dataModel.getDescription().equals("")) {
CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(dataModel.getDescription()));
msDescription.setText(bodyWithMD);
Markdown.render(context, EmojiParser.parseToUnicode(dataModel.getDescription()), msDescription);
}
else {
@ -257,14 +171,12 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
msProgress.setProgress(100);
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 100), context));
}
else {
int msCompletion = 100 * dataModel.getClosed_issues() / (dataModel.getOpen_issues() + dataModel.getClosed_issues());
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, msCompletion), context));
msProgress.setProgress(msCompletion);
}
}
@ -272,11 +184,11 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
msProgress.setProgress(0);
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 0), context));
}
if(dataModel.getDue_on() != null) {
String TAG = Constants.tagMilestonesAdapter;
if(timeFormat.equals("normal") || timeFormat.equals("pretty")) {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", new Locale(locale));
@ -293,12 +205,11 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
String dueDate = formatter.format(date);
if(date.before(new Date())) {
msDueDate.setTextColor(context.getResources().getColor(R.color.darkRed));
msDueDate.setTextColor(ResourcesCompat.getColor(context.getResources(), R.color.darkRed, null));
}
msDueDate.setText(dueDate);
msDueDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToast(dataModel.getDue_on()), context));
}
else if(timeFormat.equals("normal1")) {
@ -316,7 +227,6 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
assert date1 != null;
String dueDate = formatter.format(date1);
msDueDate.setText(dueDate);
}
}
@ -334,7 +244,6 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
dataList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, dataList.size());
}
@Override
@ -346,14 +255,12 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
else {
return 1;
}
}
@Override
public int getItemCount() {
return dataList.size();
}
static class LoadHolder extends RecyclerView.ViewHolder {
@ -362,32 +269,27 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<Milestones> list) {

View File

@ -6,26 +6,27 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.amulyakhare.textdrawable.TextDrawable;
import org.mian.gitnex.R;
import org.mian.gitnex.models.Emails;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import org.gitnex.tea4j.models.Emails;
import org.mian.gitnex.R;
import java.util.List;
/**
* Author M M Arif
*/
public class ProfileEmailsAdapter extends RecyclerView.Adapter<ProfileEmailsAdapter.EmailsViewHolder> {
public class MyProfileEmailsAdapter extends RecyclerView.Adapter<MyProfileEmailsAdapter.EmailsViewHolder> {
private List<Emails> emailsList;
private Context mCtx;
private final List<Emails> emailsList;
private final Context context;
static class EmailsViewHolder extends RecyclerView.ViewHolder {
private ImageView emailPrimary;
private TextView userEmail;
private final ImageView emailPrimary;
private final TextView userEmail;
private EmailsViewHolder(View itemView) {
super(itemView);
@ -36,20 +37,20 @@ public class ProfileEmailsAdapter extends RecyclerView.Adapter<ProfileEmailsAdap
}
}
public ProfileEmailsAdapter(Context mCtx, List<Emails> emailsListMain) {
this.mCtx = mCtx;
public MyProfileEmailsAdapter(Context ctx, List<Emails> emailsListMain) {
this.context = ctx;
this.emailsList = emailsListMain;
}
@NonNull
@Override
public ProfileEmailsAdapter.EmailsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
public MyProfileEmailsAdapter.EmailsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_profile_emails, parent, false);
return new ProfileEmailsAdapter.EmailsViewHolder(v);
return new MyProfileEmailsAdapter.EmailsViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull ProfileEmailsAdapter.EmailsViewHolder holder, int position) {
public void onBindViewHolder(@NonNull MyProfileEmailsAdapter.EmailsViewHolder holder, int position) {
Emails currentItem = emailsList.get(position);
@ -58,12 +59,12 @@ public class ProfileEmailsAdapter extends RecyclerView.Adapter<ProfileEmailsAdap
if(currentItem.getPrimary()) {
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.textColor(mCtx.getResources().getColor(R.color.colorWhite))
.textColor(ResourcesCompat.getColor(context.getResources(), R.color.colorWhite, null))
.fontSize(36)
.width(220)
.height(60)
.endConfig()
.buildRoundRect(mCtx.getResources().getString(R.string.emailTypeText), mCtx.getResources().getColor(R.color.tooltipBackground), 8);
.buildRoundRect(context.getResources().getString(R.string.emailTypeText), ResourcesCompat.getColor(context.getResources(), R.color.tooltipBackground, null), 8);
holder.emailPrimary.setImageDrawable(drawable);
}
else {

View File

@ -0,0 +1,151 @@
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.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import java.util.List;
/**
* Author M M Arif
*/
public class MyProfileFollowersAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private final int TYPE_LOAD = 0;
private List<UserInfo> followersList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public MyProfileFollowersAdapter(List<UserInfo> dataList, Context ctx) {
this.context = ctx;
this.followersList = dataList;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new MyProfileFollowersAdapter.FollowersHolder(inflater.inflate(R.layout.list_profile_followers_following, parent, false));
}
else {
return new MyProfileFollowersAdapter.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) {
((MyProfileFollowersAdapter.FollowersHolder) holder).bindData(followersList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(followersList.get(position).getUsername() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return followersList.size();
}
class FollowersHolder extends RecyclerView.ViewHolder {
private UserInfo userInfo;
private final ImageView userAvatar;
private final TextView userFullName;
private final TextView userName;
FollowersHolder(View itemView) {
super(itemView);
userAvatar = itemView.findViewById(R.id.userAvatar);
userFullName = itemView.findViewById(R.id.userFullName);
userName = itemView.findViewById(R.id.userName);
itemView.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userInfo.getLogin());
context.startActivity(intent);
});
itemView.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userInfo.getLogin(), context.getString(R.string.copyLoginIdToClipBoard, userInfo.getLogin()));
return true;
});
}
@SuppressLint("SetTextI18n")
void bindData(UserInfo userInfo) {
this.userInfo = userInfo;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
if(!userInfo.getFullname().equals("")) {
userFullName.setText(Html.fromHtml(userInfo.getFullname()));
userName.setText(context.getResources().getString(R.string.usernameWithAt, userInfo.getUsername()));
}
else {
userFullName.setText(userInfo.getUsername());
userName.setVisibility(View.GONE);
}
PicassoService.getInstance(context).get().load(userInfo.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(userAvatar);
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<UserInfo> list) {
followersList = list;
notifyDataChanged();
}
}

View File

@ -0,0 +1,149 @@
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.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import java.util.List;
/**
* Author M M Arif
*/
public class MyProfileFollowingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private final int TYPE_LOAD = 0;
private List<UserInfo> followingList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public MyProfileFollowingAdapter(List<UserInfo> dataList, Context ctx) {
this.context = ctx;
this.followingList = dataList;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new MyProfileFollowingAdapter.FollowingHolder(inflater.inflate(R.layout.list_profile_followers_following, parent, false));
}
else {
return new MyProfileFollowingAdapter.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) {
((MyProfileFollowingAdapter.FollowingHolder) holder).bindData(followingList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(followingList.get(position).getUsername() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return followingList.size();
}
class FollowingHolder extends RecyclerView.ViewHolder {
private UserInfo userInfo;
private final ImageView userAvatar;
private final TextView userFullName;
private final TextView userName;
FollowingHolder(View itemView) {
super(itemView);
userAvatar = itemView.findViewById(R.id.userAvatar);
userFullName = itemView.findViewById(R.id.userFullName);
userName = itemView.findViewById(R.id.userName);
itemView.setOnClickListener(loginId -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", userInfo.getLogin());
context.startActivity(intent);
});
itemView.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, userInfo.getLogin(), context.getString(R.string.copyLoginIdToClipBoard, userInfo.getLogin()));
return true;
});
}
@SuppressLint("SetTextI18n")
void bindData(UserInfo userInfo) {
this.userInfo = userInfo;
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
if(!userInfo.getFullname().equals("")) {
userFullName.setText(Html.fromHtml(userInfo.getFullname()));
userName.setText(context.getResources().getString(R.string.usernameWithAt, userInfo.getUsername()));
}
else {
userFullName.setText(userInfo.getUsername());
userName.setVisibility(View.GONE);
}
PicassoService.getInstance(context).get().load(userInfo.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(userAvatar);
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<UserInfo> list) {
followingList = list;
notifyDataChanged();
}
}

View File

@ -1,8 +1,5 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
@ -13,31 +10,32 @@ import android.widget.CheckBox;
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.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.gitnex.tea4j.models.UserRepositories;
import org.gitnex.tea4j.models.WatchInfo;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.RepoForksActivity;
import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Locale;
import retrofit2.Call;
import retrofit2.Callback;
@ -47,92 +45,87 @@ import retrofit2.Callback;
public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.MyReposViewHolder> implements Filterable {
private List<UserRepositories> reposList;
private Context mCtx;
private List<UserRepositories> reposListFull;
private final List<UserRepositories> reposList;
private final Context context;
private final List<UserRepositories> reposListFull;
static class MyReposViewHolder extends RecyclerView.ViewHolder {
private ImageView imageAvatar;
private TextView repoName;
private TextView repoDescription;
private TextView repoFullName;
private ImageView repoPrivatePublic;
private TextView repoStars;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private UserRepositories userRepositories;
private final ImageView image;
private final TextView repoName;
private final TextView orgName;
private final TextView repoDescription;
private CheckBox isRepoAdmin;
private LinearLayout archiveRepo;
private TextView repoBranch;
private TextView htmlUrl;
private final TextView repoStars;
private final TextView repoLastUpdated;
private final View spacerView;
private MyReposViewHolder(View itemView) {
super(itemView);
repoName = itemView.findViewById(R.id.repoName);
orgName = itemView.findViewById(R.id.orgName);
repoDescription = itemView.findViewById(R.id.repoDescription);
imageAvatar = itemView.findViewById(R.id.imageAvatar);
repoFullName = 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);
repoType = itemView.findViewById(R.id.repoType);
isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
repoBranch = itemView.findViewById(R.id.repoBranch);
htmlUrl = itemView.findViewById(R.id.htmlUrl);
image = itemView.findViewById(R.id.imageAvatar);
repoStars = itemView.findViewById(R.id.repoStars);
repoLastUpdated = itemView.findViewById(R.id.repoLastUpdated);
spacerView = itemView.findViewById(R.id.spacerView);
itemView.setOnClickListener(v -> {
Context context = v.getContext();
TinyDB tinyDb = TinyDB.getInstance(context);
Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", repoFullName.getText().toString());
intent.putExtra("repoFullName", userRepositories.getFullName());
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putString("repoType", repoType.getText().toString());
tinyDb.putString("repoFullName", userRepositories.getFullName());
//tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
tinyDb.putString("repoBranch", repoBranch.getText().toString());
tinyDb.putString("repoBranch", userRepositories.getDefault_branch());
String[] parts = repoFullName.getText().toString().split("/");
if(userRepositories.getPrivateFlag()) {
tinyDb.putString("repoType", context.getResources().getString(R.string.strPrivate));
}
else {
tinyDb.putString("repoType", context.getResources().getString(R.string.strPublic));
}
String[] parts = userRepositories.getFullName().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context);
RepositoriesApi repositoryData = BaseApi.getInstance(context, RepositoriesApi.class);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
assert repositoryData != null;
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchInfo watch = new WatchInfo();
Call<WatchInfo> call;
call = RetrofitClient.getInstance(instanceUrl, context).getApiInterface().checkRepoWatchStatus(token, repoOwner, repoName);
call = RetrofitClient.getApiInterface(context).checkRepoWatchStatus(token, repoOwner, repoName);
call.enqueue(new Callback<WatchInfo>() {
@ -173,81 +166,13 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
context.startActivity(intent);
});
reposDropdownMenu.setOnClickListener(v -> {
final Context context = v.getContext();
@SuppressLint("InflateParams") View view = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_repository_in_list, null);
TextView repoOpenInBrowser = view.findViewById(R.id.repoOpenInBrowser);
TextView repoStargazers = view.findViewById(R.id.repoStargazers);
TextView repoWatchers = view.findViewById(R.id.repoWatchers);
TextView repoForksList = view.findViewById(R.id.repoForksList);
TextView repoCopyUrl = view.findViewById(R.id.repoCopyUrl);
TextView bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader);
bottomSheetHeader.setText(String.format("%s / %s", repoFullName.getText().toString().split("/")[0], repoFullName.getText().toString().split("/")[1]));
BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view);
dialog.show();
repoCopyUrl.setOnClickListener(openInBrowser -> {
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(context).getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("repoUrl", htmlUrl.getText().toString());
assert clipboard != null;
clipboard.setPrimaryClip(clip);
Toasty.info(context, context.getString(R.string.copyIssueUrlToastMsg));
dialog.dismiss();
});
repoOpenInBrowser.setOnClickListener(openInBrowser -> {
Intent intentOpenInBrowser = new Intent(context, OpenRepoInBrowserActivity.class);
intentOpenInBrowser.putExtra("repoFullNameBrowser", repoFullName.getText());
context.startActivity(intentOpenInBrowser);
dialog.dismiss();
});
repoStargazers.setOnClickListener(stargazers -> {
Intent intent = new Intent(context, RepoStargazersActivity.class);
intent.putExtra("repoFullNameForStars", repoFullName.getText());
context.startActivity(intent);
dialog.dismiss();
});
repoWatchers.setOnClickListener(watchers -> {
Intent intentW = new Intent(context, RepoWatchersActivity.class);
intentW.putExtra("repoFullNameForWatchers", repoFullName.getText());
context.startActivity(intentW);
dialog.dismiss();
});
repoForksList.setOnClickListener(forks -> {
Intent intentW = new Intent(context, RepoForksActivity.class);
intentW.putExtra("repoFullNameForForks", repoFullName.getText());
context.startActivity(intentW);
dialog.dismiss();
});
});
}
}
public MyReposListAdapter(Context mCtx, List<UserRepositories> reposListMain) {
public MyReposListAdapter(Context ctx, List<UserRepositories> reposListMain) {
this.mCtx = mCtx;
this.context = ctx;
this.reposList = reposListMain;
reposListFull = new ArrayList<>(reposList);
}
@ -263,59 +188,77 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
@Override
public void onBindViewHolder(@NonNull MyReposListAdapter.MyReposViewHolder holder, int position) {
TinyDB tinyDb = TinyDB.getInstance(context);
UserRepositories currentItem = reposList.get(position);
holder.repoDescription.setVisibility(View.GONE);
holder.repoBranch.setText(currentItem.getDefault_branch());
holder.htmlUrl.setText(currentItem.getHtml_url());
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
Locale locale = context.getResources().getConfiguration().locale;
String timeFormat = tinyDb.getString("dateFormat");
holder.userRepositories = currentItem;
holder.orgName.setText(currentItem.getFullName().split("/")[0]);
holder.repoName.setText(currentItem.getFullName().split("/")[1]);
holder.repoStars.setText(currentItem.getStars_count());
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
String firstCharacter = String.valueOf(currentItem.getName().charAt(0));
String firstCharacter = String.valueOf(currentItem.getFullName().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("")) {
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.imageAvatar);
PicassoService.getInstance(context).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(holder.image);
}
else {
holder.imageAvatar.setImageDrawable(drawable);
holder.image.setImageDrawable(drawable);
}
}
else {
holder.imageAvatar.setImageDrawable(drawable);
holder.image.setImageDrawable(drawable);
}
if(currentItem.getUpdated_at() != null) {
switch(timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(locale);
String createdTime = prettyTime.format(currentItem.getUpdated_at());
holder.repoLastUpdated.setText(context.getString(R.string.lastUpdatedAt, createdTime));
holder.repoLastUpdated.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getUpdated_at()), context));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", locale);
String createdTime = formatter.format(currentItem.getUpdated_at());
holder.repoLastUpdated.setText(context.getString(R.string.lastUpdatedAt, createdTime));
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", locale);
String createdTime = formatter.format(currentItem.getUpdated_at());
holder.repoLastUpdated.setText(context.getString(R.string.lastUpdatedAt, createdTime));
break;
}
}
}
else {
holder.repoLastUpdated.setVisibility(View.GONE);
}
holder.repoName.setText(currentItem.getName());
if(!currentItem.getDescription().equals("")) {
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.repoFullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
holder.spacerView.setVisibility(View.GONE);
}
else {
holder.repoPrivatePublic.setVisibility(View.GONE);
holder.repoType.setText(R.string.strPublic);
holder.repoDescription.setVisibility(View.GONE);
holder.spacerView.setVisibility(View.VISIBLE);
}
holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count());
holder.repoOpenIssuesCount.setText(currentItem.getOpen_issues_count());
if(holder.isRepoAdmin == null) {
holder.isRepoAdmin = new CheckBox(mCtx);
holder.isRepoAdmin = new CheckBox(context);
}
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
}
@Override
@ -330,7 +273,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
return myReposFilter;
}
private Filter myReposFilter = new Filter() {
private final Filter myReposFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {

View File

@ -1,7 +1,7 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -9,51 +9,94 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.text.HtmlCompat;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.NotificationThread;
import org.mian.gitnex.R;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.NotificationThread;
import java.util.List;
/**
* Author opyale
* Modified M M Arif
*/
public class NotificationsAdapter extends RecyclerView.Adapter<NotificationsAdapter.NotificationsViewHolder> {
public class NotificationsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private final Context context;
private final int TYPE_LOAD = 0;
private List<NotificationThread> notificationThreads;
private OnMoreClickedListener onMoreClickedListener;
private OnNotificationClickedListener onNotificationClickedListener;
private TinyDB tinyDb;
private final OnMoreClickedListener onMoreClickedListener;
private final OnNotificationClickedListener onNotificationClickedListener;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
private final TinyDB tinyDb;
public NotificationsAdapter(Context context, List<NotificationThread> notificationThreads, OnMoreClickedListener onMoreClickedListener, OnNotificationClickedListener onNotificationClickedListener) {
this.tinyDb = new TinyDB(context);
this.tinyDb = TinyDB.getInstance(context);
this.context = context;
this.notificationThreads = notificationThreads;
this.onMoreClickedListener = onMoreClickedListener;
this.onNotificationClickedListener = onNotificationClickedListener;
}
static class NotificationsViewHolder extends RecyclerView.ViewHolder {
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new NotificationsAdapter.NotificationsHolder(inflater.inflate(R.layout.list_notifications, parent, false));
}
else {
return new NotificationsAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
private LinearLayout frame;
private TextView subject;
private TextView repository;
private ImageView typePr;
private ImageView typeIssue;
private ImageView typeUnknown;
private ImageView pinned;
private ImageView more;
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
public NotificationsViewHolder(@NonNull View itemView) {
if(getItemViewType(position) == TYPE_LOAD) {
((NotificationsAdapter.NotificationsHolder) holder).bindData(notificationThreads.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(notificationThreads.get(position).getSubject() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return notificationThreads.size();
}
class NotificationsHolder extends RecyclerView.ViewHolder {
private final LinearLayout frame;
private final TextView subject;
private final TextView repository;
private final ImageView typePr;
private final ImageView typeIssue;
private final ImageView typeUnknown;
private final ImageView pinned;
private final ImageView more;
NotificationsHolder(View itemView) {
super(itemView);
frame = itemView.findViewById(R.id.frame);
subject = itemView.findViewById(R.id.subject);
repository = itemView.findViewById(R.id.repository);
@ -62,105 +105,103 @@ public class NotificationsAdapter extends RecyclerView.Adapter<NotificationsAdap
typeUnknown = itemView.findViewById(R.id.typeUnknown);
pinned = itemView.findViewById(R.id.pinned);
more = itemView.findViewById(R.id.more);
}
}
@NonNull
@Override
public NotificationsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.list_notifications, parent, false);
return new NotificationsAdapter.NotificationsViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull NotificationsViewHolder holder, int position) {
NotificationThread notificationThread = notificationThreads.get(position);
String url = notificationThread.getSubject().getUrl();
String subjectId = "<font color='" + context.getResources().getColor(R.color.lightGray) + "'>" + context.getResources()
.getString(R.string.hash) + url.substring(url.lastIndexOf("/") + 1) + "</font>";
holder.subject.setText(Html.fromHtml(subjectId + " " + notificationThread.getSubject().getTitle()));
holder.repository.setText(notificationThread.getRepository().getFullName());
if(notificationThread.isPinned()) {
holder.pinned.setVisibility(View.VISIBLE);
}
else {
holder.pinned.setVisibility(View.GONE);
}
switch(notificationThread.getSubject().getType()) {
@SuppressLint("SetTextI18n")
void bindData(NotificationThread notificationThread) {
case "Pull":
holder.typePr.setVisibility(View.VISIBLE);
holder.typeIssue.setVisibility(View.GONE);
holder.typeUnknown.setVisibility(View.GONE);
break;
String url = notificationThread.getSubject().getUrl();
String subjectId = "<font color='" + ResourcesCompat.getColor(context.getResources(), R.color.lightGray, null) + "'>" + context.getResources().getString(R.string.hash) + url.substring(url.lastIndexOf("/") + 1) + "</font>";
case "Issue":
holder.typePr.setVisibility(View.GONE);
holder.typeIssue.setVisibility(View.VISIBLE);
holder.typeUnknown.setVisibility(View.GONE);
break;
default:
holder.typePr.setVisibility(View.GONE);
holder.typeIssue.setVisibility(View.GONE);
holder.typeUnknown.setVisibility(View.VISIBLE);
break;
}
holder.frame.setOnClickListener(v -> {
onNotificationClickedListener.onNotificationClicked(notificationThread);
String[] parts = notificationThread.getRepository().getFullName().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
subject.setText(HtmlCompat.fromHtml(subjectId + " " + notificationThread.getSubject().getTitle(), HtmlCompat.FROM_HTML_MODE_LEGACY));
repository.setText(notificationThread.getRepository().getFullName());
if(notificationThread.isPinned()) {
pinned.setVisibility(View.VISIBLE);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
pinned.setVisibility(View.GONE);
}
});
holder.more.setOnClickListener(v -> onMoreClickedListener.onMoreClicked(notificationThread));
switch(notificationThread.getSubject().getType()) {
case "Pull":
typePr.setVisibility(View.VISIBLE);
typeIssue.setVisibility(View.GONE);
typeUnknown.setVisibility(View.GONE);
break;
case "Issue":
typePr.setVisibility(View.GONE);
typeIssue.setVisibility(View.VISIBLE);
typeUnknown.setVisibility(View.GONE);
break;
default:
typePr.setVisibility(View.GONE);
typeIssue.setVisibility(View.GONE);
typeUnknown.setVisibility(View.VISIBLE);
break;
}
frame.setOnClickListener(v -> {
onNotificationClickedListener.onNotificationClicked(notificationThread);
String[] parts = notificationThread.getRepository().getFullName().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = BaseApi.getInstance(context, RepositoriesApi.class);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
});
more.setOnClickListener(v -> onMoreClickedListener.onMoreClicked(notificationThread));
}
}
@Override
public int getItemCount() {
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
return notificationThreads.size();
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<NotificationThread> list) {
notificationThreads = list;
notifyDataChanged();
}
public interface OnNotificationClickedListener {
void onNotificationClicked(NotificationThread notificationThread);
}
public interface OnMoreClickedListener {
void onMoreClicked(NotificationThread notificationThread);
}
}

View File

@ -12,12 +12,13 @@ import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.UserOrganizations;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OrganizationDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserOrganizations;
import java.util.ArrayList;
import java.util.List;
@ -27,46 +28,42 @@ import java.util.List;
public class OrganizationsListAdapter extends RecyclerView.Adapter<OrganizationsListAdapter.OrganizationsViewHolder> implements Filterable {
private List<UserOrganizations> orgList;
private Context mCtx;
private List<UserOrganizations> orgListFull;
private final List<UserOrganizations> orgList;
private final Context context;
private final List<UserOrganizations> orgListFull;
static class OrganizationsViewHolder extends RecyclerView.ViewHolder {
private ImageView image;
private TextView mTextView1;
private TextView mTextView2;
private TextView organizationId;
private UserOrganizations userOrganizations;
private final ImageView image;
private final TextView orgName;
private final TextView orgDescription;
private OrganizationsViewHolder(View itemView) {
super(itemView);
mTextView1 = itemView.findViewById(R.id.orgUsername);
mTextView2 = itemView.findViewById(R.id.orgDescription);
orgName = itemView.findViewById(R.id.orgName);
orgDescription = itemView.findViewById(R.id.orgDescription);
image = itemView.findViewById(R.id.imageAvatar);
organizationId = itemView.findViewById(R.id.organizationId);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
itemView.setOnClickListener(v -> {
Context context = v.getContext();
Intent intent = new Intent(context, OrganizationDetailActivity.class);
intent.putExtra("orgName", mTextView1.getText().toString());
Context context = v.getContext();
Intent intent = new Intent(context, OrganizationDetailActivity.class);
intent.putExtra("orgName", userOrganizations.getUsername());
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("orgName", mTextView1.getText().toString());
tinyDb.putString("organizationId", organizationId.getText().toString());
tinyDb.putBoolean("organizationAction", true);
context.startActivity(intent);
}
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("orgName", userOrganizations.getUsername());
tinyDb.putString("organizationId", String.valueOf(userOrganizations.getId()));
tinyDb.putBoolean("organizationAction", true);
context.startActivity(intent);
});
}
}
public OrganizationsListAdapter(Context mCtx, List<UserOrganizations> orgsListMain) {
this.mCtx = mCtx;
public OrganizationsListAdapter(Context ctx, List<UserOrganizations> orgsListMain) {
this.context = ctx;
this.orgList = orgsListMain;
orgListFull = new ArrayList<>(orgList);
}
@ -74,6 +71,7 @@ public class OrganizationsListAdapter extends RecyclerView.Adapter<Organizations
@NonNull
@Override
public OrganizationsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_organizations, parent, false);
return new OrganizationsViewHolder(v);
}
@ -83,16 +81,20 @@ public class OrganizationsListAdapter extends RecyclerView.Adapter<Organizations
public void onBindViewHolder(@NonNull OrganizationsViewHolder holder, int position) {
UserOrganizations currentItem = orgList.get(position);
holder.mTextView2.setVisibility(View.GONE);
holder.organizationId.setText(Integer.toString(currentItem.getId()));
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).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);
holder.mTextView2.setText(currentItem.getDescription());
}
holder.userOrganizations = currentItem;
holder.orgName.setText(currentItem.getUsername());
PicassoService.getInstance(context).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(holder.image);
if(!currentItem.getDescription().equals("")) {
holder.orgDescription.setVisibility(View.VISIBLE);
holder.orgDescription.setText(currentItem.getDescription());
}
else {
holder.orgDescription.setVisibility(View.GONE);
}
}
@Override
@ -105,14 +107,19 @@ public class OrganizationsListAdapter extends RecyclerView.Adapter<Organizations
return orgFilter;
}
private Filter orgFilter = new Filter() {
private final Filter orgFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<UserOrganizations> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(orgListFull);
} else {
}
else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (UserOrganizations item : orgListFull) {
@ -130,6 +137,7 @@ public class OrganizationsListAdapter extends RecyclerView.Adapter<Organizations
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
orgList.clear();
orgList.addAll((List) results.values);
notifyDataSetChanged();

View File

@ -1,78 +0,0 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
/**
* Author M M Arif
*/
public class ProfileFollowersAdapter extends RecyclerView.Adapter<ProfileFollowersAdapter.FollowersViewHolder> {
private List<UserInfo> followersList;
private Context mCtx;
static class FollowersViewHolder extends RecyclerView.ViewHolder {
private ImageView userAvatar;
private TextView userFullName;
private TextView userName;
private FollowersViewHolder(View itemView) {
super(itemView);
userAvatar = itemView.findViewById(R.id.userAvatar);
userFullName = itemView.findViewById(R.id.userFullName);
userName = itemView.findViewById(R.id.userName);
}
}
public ProfileFollowersAdapter(Context mCtx, List<UserInfo> followersListMain) {
this.mCtx = mCtx;
this.followersList = followersListMain;
}
@NonNull
@Override
public ProfileFollowersAdapter.FollowersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_profile_followers, parent, false);
return new ProfileFollowersAdapter.FollowersViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull ProfileFollowersAdapter.FollowersViewHolder holder, int position) {
UserInfo currentItem = followersList.get(position);
if(!currentItem.getFullname().equals("")) {
holder.userFullName.setText(currentItem.getFullname());
holder.userName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getUsername()));
}
else {
holder.userFullName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getUsername()));
holder.userName.setVisibility(View.GONE);
}
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
}
@Override
public int getItemCount() {
return followersList.size();
}
}

View File

@ -1,77 +0,0 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
/**
* Author M M Arif
*/
public class ProfileFollowingAdapter extends RecyclerView.Adapter<ProfileFollowingAdapter.FollowingViewHolder> {
private List<UserInfo> followingList;
private Context mCtx;
static class FollowingViewHolder extends RecyclerView.ViewHolder {
private ImageView userAvatar;
private TextView userFullName;
private TextView userName;
private FollowingViewHolder(View itemView) {
super(itemView);
userAvatar = itemView.findViewById(R.id.userAvatar);
userFullName = itemView.findViewById(R.id.userFullName);
userName = itemView.findViewById(R.id.userName);
}
}
public ProfileFollowingAdapter(Context mCtx, List<UserInfo> followingListMain) {
this.mCtx = mCtx;
this.followingList = followingListMain;
}
@NonNull
@Override
public ProfileFollowingAdapter.FollowingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_profile_following, parent, false);
return new ProfileFollowingAdapter.FollowingViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull ProfileFollowingAdapter.FollowingViewHolder holder, int position) {
UserInfo currentItem = followingList.get(position);
if(!currentItem.getFullname().equals("")) {
holder.userFullName.setText(currentItem.getFullname());
holder.userName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getUsername()));
}
else {
holder.userFullName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getUsername()));
holder.userName.setVisibility(View.GONE);
}
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
}
@Override
public int getItemCount() {
return followingList.size();
}
}

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