Compare commits

...

102 Commits

Author SHA1 Message Date
Shihaam Abdul Rahman
b2604c1650 added mine and athafans domains 2021-11-04 23:20:31 +05:00
M M Arif
a4dee6a179 Update readme (#1013)
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1013
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-11-01 09:15:55 +01:00
M M Arif
8d69c7b9ce Update CI (#1012)
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1012
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-11-01 09:11:10 +01:00
M M Arif
367380921f Update CI (#1011)
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1011
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-11-01 08:00:52 +01:00
qwerty287
471889f744 Fix CI (#1010)
* replace docker image with newer version (tested locally, `curl` and `apksigner` are available)
* update the container before signing. This is necessary because `curl` is outdated, but can be updated via `apt` (tested locally, working **only** after update)

I hope this way is fine, I don't really anything about docker and just tried to fix it :)

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1010
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-31 21:26:08 +01:00
qwerty287
84551ca8be Split issue templates (#999)
Split the issue templates into `Bug`, `Feature` and `Suggestion`.

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/999
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-24 14:55:48 +02:00
qwerty287
b4d08a6733 Improve behavior of Android's back button in file browser (#1006)
Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1006
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-24 12:17:54 +02:00
qwerty287
2cf702982a Fix crash on issue search (#1005)
Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1005
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-24 12:10:22 +02:00
qwerty287
65ca86847f Update README (#1004)
* fix typo
* remove link to archived website repo
* change `F-droid` to `F-Droid`

Co-authored-by: qwerty287 <ndev@web.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1004
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2021-10-20 18:12:05 +02:00
M M Arif
64b9b07a9e CI (#998)
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/998
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-10-14 21:20:27 +02:00
M M Arif
d5cf4295bd Check CI (#997)
As title

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/997
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-10-14 20:40:51 +02:00
M M Arif
8b0e3ee53d Kick start 4.2.0 (#996)
As title

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/996
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-committed-by: M M Arif <mmarif@noreply.codeberg.org>
2021-10-14 17:08:17 +02:00
Epsilon_02
a2cf46a896 Fix newline glitch on issue description. (#995)
### Describe what your pull request does and which issue you’re targeting
A single newline did not work in the description. Only with two newlines they are shown but now as two newlines.
<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: Epsilon_02 <epsilon_02+codeberg@mailbox.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/995
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: Epsilon_02 <epsilon_02@noreply.codeberg.org>
Co-committed-by: Epsilon_02 <epsilon_02@noreply.codeberg.org>
2021-10-14 17:04:08 +02:00
M M Arif
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
6543
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
M M Arif
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
qwerty287
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
qwerty287
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
M M Arif
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
M M Arif
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
M M Arif
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
qwerty287
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
qwerty287
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
qwerty287
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
qwerty287
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
M M Arif
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
M M Arif
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
M M Arif
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
M M Arif
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
qwerty287
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
M M Arif
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
M M Arif
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
qwerty287
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
qwerty287
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
qwerty287
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
qwerty287
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
qwerty287
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
M M Arif
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
opyale
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
qwerty287
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
M M Arif
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
qwerty287
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
qwerty287
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
M M Arif
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
qwerty287
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
qwerty287
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
M M Arif
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
M M Arif
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
qwerty287
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
opyale
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
qwerty287
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
opyale
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
M M Arif
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
M M Arif
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
opyale
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
M M Arif
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
opyale
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
M M Arif
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
opyale
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
M M Arif
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
opyale
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
opyale
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
M M Arif
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
M M Arif
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
opyale
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
M M Arif
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
6543
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
6543
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
opyale
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
opyale
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
6543
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
M M Arif
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
M M Arif
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
M M Arif
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
M M Arif
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
opyale
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
6543
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
M M Arif
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
M M Arif
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
opyale
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
opyale
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
M M Arif
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
6543
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
6543
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
opyale
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
opyale
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
opyale
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
M M Arif
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
M M Arif
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
opyale
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
opyale
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
opyale
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
opyale
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
M M Arif
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
M M Arif
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
opyale
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
opyale
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
opyale
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
M M Arif
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
opyale
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
opyale
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
M M Arif
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
479 changed files with 16597 additions and 16277 deletions

View File

@ -15,8 +15,8 @@ steps:
image: zosiab/eclint:latest image: zosiab/eclint:latest
depends_on: [ clone ] depends_on: [ clone ]
commands: commands:
- git pull origin master - git pull origin main
- eclint check $(git diff --name-only origin/master) - 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. # 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 # Additional information: https://www.jetbrains.com/help/idea/command-line-formatter.html
@ -54,7 +54,7 @@ trigger:
event: event:
- push - push
branch: branch:
- master - main
--- ---
kind: pipeline kind: pipeline
@ -101,4 +101,4 @@ trigger:
event: event:
- push - push
branch: branch:
- master - main

View File

@ -1,22 +1,22 @@
## # What do you want to address? ---
<!-- This step is required; examples are shown below -->
- [ ] Bug name: "Bug"
- [ ] Feature about: "Something isn't working"
- [ ] Suggestion labels:
- Bug
---
## # Describe your matter briefly ## # Describe your matter briefly
<!-- This step is required. -->
<br><br> <br><br>
##### What did you expect? <!-- Useful when addressing bugs --> ##### What did you expect?
--- ---
<!-- This step is optional. -->
<br><br> <br><br>
##### Some additional details <!-- Useful, when we are trying to reproduce a bug --> ##### Some additional details
--- ---
<!-- This step is optional; an example is shown below -->
* The version of **Gitea** you are using: * The version of **Gitea** you are using:
* The version of **GitNex** you are using: * The version of **GitNex** you are using:
@ -31,7 +31,7 @@
<!-- Screenshots and stacktrace's can go here. --> <!-- Screenshots and stacktrace's can go here. -->
<br><br> <br><br>
- [ ] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/master/CONTRIBUTING.md). - [ ] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/main/CONTRIBUTING.md).
<br> <br>
#### Thank you for your time. <!-- Thank you for your time. -->

View File

@ -0,0 +1,17 @@
---
name: "Feature"
about: "A new feature or an enhancement to an existing feature"
labels:
- Feature
---
## # Describe your matter briefly
<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

@ -0,0 +1,37 @@
---
name: "Suggestion"
about: "A general suggestion"
labels:
- Suggestion
---
## # Describe your matter briefly
<br><br>
##### What did you expect?
---
<br><br>
##### Some additional details
---
* The version of **Gitea** you are using:
* The version of **GitNex** you are using:
* 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. -->
<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

@ -2,8 +2,8 @@
<!-- Create a new issue, if it doesn't exist yet --> <!-- Create a new issue, if it doesn't exist yet -->
<br><br> <br><br>
<!-- Make sure you are targeting the master branch, pull requests on release branches are only allowed for bug fixes. --> <!-- Make sure you are targeting the "main" branch, pull requests on release branches are only allowed for bug fixes. -->
- [ ] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/master/CONTRIBUTING.md). - [ ] 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). - [ ] 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/master/LICENSE). - [ ] 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 !/gradle/wrapper/gradle-wrapper.jar
# End of https://www.gitignore.io/api/android,androidstudio # End of https://www.gitignore.io/api/android,androidstudio
# Crowdin Config
crowdin.yml

View File

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

@ -29,7 +29,7 @@ It is documented in the Wiki: [Code-Standards](https://codeberg.org/gitnex/GitNe
2. Clone the forked repository from your namespace to your local machine. 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. 3. Create a new branch and work on your feature, enhancement or patch.
4. Push your commits to your forked version. 4. Push your commits to your forked version.
5. You can now create a PR using the web interface against **master** branch. 5. You can now create a PR using the web interface against **main** branch.
For more information, click [here](http://makeapullrequest.com/). For more information, click [here](http://makeapullrequest.com/).

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)](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) [![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/mmarif4u/gitnex-ci/main)](https://gitlab.com/mmarif4u/gitnex-ci/-/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="Become a Patreon" 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 - 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 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 ## 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 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='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/raw/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 ## Note about Gitea version
Please make sure that you are on latest stable release or later for better app experience. 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) - [MANY MORE](https://codeberg.org/gitnex/GitNex/wiki/Features)
## Contributing ## Contributing
[CONTRIBUTING](https://codeberg.org/gitnex/GitNex/src/branch/master/CONTRIBUTING.md) [CONTRIBUTING](https://codeberg.org/gitnex/GitNex/src/branch/main/CONTRIBUTING.md)
## Translation ## Translation
Help us translate GitNex to your native language. Help us translate GitNex to your native language.
@ -48,46 +48,50 @@ We use [Crowdin](https://crowdin.com/project/gitnex) for translation. If your la
## Screenshots: ## 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"/> <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"/>
## FAQ
[Faq](https://codeberg.org/gitnex/GitNex/wiki/FAQ)
## Links ## Links
[Website](https://gitnex.com) [Website](https://gitnex.com)
[Wiki](https://codeberg.org/gitnex/GitNex/wiki/Home) [Wiki](https://codeberg.org/gitnex/GitNex/wiki/Home)
[Website Repository](https://gitlab.com/mmarif4u/gitnex-website)
[Troubleshoot Guide](https://codeberg.org/gitnex/GitNex/wiki/Troubleshoot-Guide) [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
Thanks to all the open source libraries, contributors and donators. Thanks to all the open source libraries, contributors and donators.
#### Open source libraries #### Open source libraries
- Retrofit - [square/retrofit](https://github.com/square/retrofit)
- Gson - [google/gson](https://github.com/google/gson)
- Okhttp - [square/okhttp](https://github.com/square/okhttp)
- Picasso - [square/picasso](https://github.com/square/picasso)
- Markwon - [wasabeef/picasso-transformations](https://github.com/wasabeef/picasso-transformations)
- Prism4j - [cats-oss/android-gpuimage](https://github.com/cats-oss/android-gpuimage)
- Prettytime - [noties/Markwon](https://github.com/noties/Markwon)
- Amulyakhare/textdrawable - [noties/Prism4j](https://github.com/noties/Prism4j)
- Vdurmont/emoji-java - [ocpsoft/prettytime](https://github.com/ocpsoft/prettytime)
- Pes/materialcolorpicker - [amulyakhare/TextDrawable](https://github.com/amulyakhare/TextDrawable)
- HamidrezaAmz/BreadcrumbsView - [vdurmont/emoji-java](https://github.com/vdurmont/emoji-java)
- Chrisbanes/PhotoView - [Pes8/android-material-color-picker-dialog](https://github.com/Pes8/android-material-color-picker-dialog)
- Pddstudio/highlightjs-android - [HamidrezaAmz/BreadcrumbsView](https://github.com/HamidrezaAmz/BreadcrumbsView)
- Apache/commons-io - [Baseflow/PhotoView](https://github.com/Baseflow/PhotoView)
- Caverock/androidsvg - [apache/commons](https://github.com/apache/commons-io)
- Droidsonroids.gif/android-gif-drawable - [ge0rg/MemorizingTrustManager](https://github.com/ge0rg/MemorizingTrustManager)
- Barteksc/androidPdfViewer - [mikaelhg/urlbuilder](https://github.com/mikaelhg/urlbuilder)
- Ge0rg/memorizingTrustManager - [ACRA/acra](https://github.com/ACRA/acra)
- Dimezis/blurView - [chrisvest/stormpot](https://github.com/chrisvest/stormpot)
- Mikaelhg/urlbuilder
#### 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) [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" applicationId "org.mian.gitnex"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 30 targetSdkVersion 30
versionCode 336 versionCode 415
versionName "3.4.0-dev" versionName "4.2.0"
multiDexEnabled true multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@ -24,13 +24,13 @@ android {
} }
} }
buildFeatures { buildFeatures {
viewBinding = true viewBinding true
} }
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
shrinkResources false shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
lintOptions { lintOptions {
@ -54,28 +54,31 @@ configurations {
} }
dependencies { dependencies {
def lifecycle_version = '2.3.0-rc01' def lifecycle_version = '2.3.1'
def markwon_version = '4.6.1' def markwon_version = '4.6.2'
def work_version = "2.4.0" def work_version = "2.7.0-alpha05"
def acra = "5.7.0" def acra = "5.7.0"
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.3.0-alpha02' implementation 'androidx.appcompat:appcompat:1.4.0-alpha03'
implementation 'com.google.android.material:material:1.3.0-alpha03' implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
testImplementation 'junit:junit:4.13.1' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:runner:1.3.0' androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.0' implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
implementation "com.google.code.gson:gson:2.8.6" implementation "com.google.code.gson:gson:2.8.6"
implementation "com.squareup.picasso:picasso:2.71828" 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.amulyakhare:com.amulyakhare.textdrawable:1.0.1"
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0' implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2'
implementation 'org.ocpsoft.prettytime:prettytime:5.0.0.Final' implementation 'org.ocpsoft.prettytime:prettytime:5.0.0.Final'
implementation "com.pes.materialcolorpicker:library:1.2.5" implementation "com.pes.materialcolorpicker:library:1.2.5"
implementation "io.noties.markwon:core:$markwon_version" implementation "io.noties.markwon:core:$markwon_version"
@ -94,22 +97,21 @@ dependencies {
implementation "io.noties.markwon:image-picasso:$markwon_version" implementation "io.noties.markwon:image-picasso:$markwon_version"
implementation "io.noties:prism4j:2.0.0" implementation "io.noties:prism4j:2.0.0"
annotationProcessor "io.noties:prism4j-bundler:2.0.0" annotationProcessor "io.noties:prism4j-bundler:2.0.0"
implementation "com.caverock:androidsvg:1.4"
implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.21"
implementation "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9" implementation "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9"
implementation "commons-io:commons-io:20030203.000550" 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.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-mail:$acra"
implementation "ch.acra:acra-limiter:$acra" implementation "ch.acra:acra-limiter:$acra"
implementation "ch.acra:acra-notification:$acra" implementation "ch.acra:acra-notification:$acra"
implementation 'androidx.room:room-runtime:2.2.6' implementation 'androidx.room:room-runtime:2.3.0'
annotationProcessor 'androidx.room:room-compiler:2.2.6' annotationProcessor 'androidx.room:room-compiler:2.3.0'
implementation "androidx.work:work-runtime:$work_version" implementation "androidx.work:work-runtime:$work_version"
implementation "com.eightbitlab:blurview:1.6.4"
implementation "io.mikael:urlbuilder:2.0.9" implementation "io.mikael:urlbuilder:2.0.9"
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2" implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.1" 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 # If you keep the line number information, uncomment this to
# hide the original source file name. # hide the original source file name.
#-renamesourcefileattribute SourceFile #-renamesourcefileattribute SourceFile
-optimizationpasses 30
-allowaccessmodification

View File

@ -6,11 +6,13 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<application <application
android:name=".core.MainApplication"
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/app_logo" android:icon="@mipmap/app_logo"
android:label="@string/app_name" android:label="@string/appName"
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
android:resizeableActivity="true" android:resizeableActivity="true"
android:roundIcon="@mipmap/app_logo_round" android:roundIcon="@mipmap/app_logo_round"
@ -49,7 +51,7 @@
android:name=".activities.CreateNewUserActivity" android:name=".activities.CreateNewUserActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" /> android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity <activity
android:name=".activities.ProfileEmailActivity" android:name=".activities.MyProfileEmailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" /> android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity <activity
android:name=".activities.AddCollaboratorToRepositoryActivity" android:name=".activities.AddCollaboratorToRepositoryActivity"
@ -63,7 +65,7 @@
<activity <activity
android:name=".activities.OrganizationDetailActivity" android:name=".activities.OrganizationDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" 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" /> android:theme="@style/AppTheme.NoActionBar" />
<activity <activity
android:name=".activities.CreateLabelActivity" android:name=".activities.CreateLabelActivity"
@ -81,12 +83,13 @@
<activity <activity
android:name=".activities.RepoDetailActivity" android:name=".activities.RepoDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" 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" /> android:theme="@style/AppTheme.NoActionBar" />
<activity <activity
android:name=".activities.MainActivity" android:name=".activities.MainActivity"
android:theme="@android:style/Theme.NoTitleBar" 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> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -121,7 +124,7 @@
android:name=".activities.SettingsAppearanceActivity" android:name=".activities.SettingsAppearanceActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" /> android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity <activity
android:name=".activities.SettingsFileViewerActivity" android:name=".activities.ProfileActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" /> android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity <activity
android:name=".activities.SettingsSecurityActivity" android:name=".activities.SettingsSecurityActivity"
@ -157,6 +160,10 @@
android:name=".activities.SettingsNotificationsActivity" android:name=".activities.SettingsNotificationsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" /> 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 --> <!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/> <meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>
<!-- Version >= 3.0. DeX Dual Mode support --> <!-- Version >= 3.0. DeX Dual Mode support -->
@ -167,7 +174,8 @@
android:name=".activities.DeepLinksActivity" android:name=".activities.DeepLinksActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar" android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:noHistory="true" android:noHistory="true"
android:launchMode="singleTask"> android:launchMode="singleTask"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
@ -181,6 +189,10 @@
<data android:host="code.obermui.de" /> <data android:host="code.obermui.de" />
<data android:host="git.fsfe.org" /> <data android:host="git.fsfe.org" />
<data android:host="opendev.org" /> <data android:host="opendev.org" />
<data android:host="git.shihaam.dev" />
<data android:host="git.athfan.com" />
<data android:host="git.athfan.dev" />
</intent-filter> </intent-filter>
</activity> </activity>

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.util.Log;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; 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.R;
import org.mian.gitnex.adapters.AssigneesListAdapter; import org.mian.gitnex.adapters.AssigneesListAdapter;
import org.mian.gitnex.clients.RetrofitClient; 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.Authorization;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import java.util.List; import java.util.List;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;

View File

@ -3,6 +3,8 @@ package org.mian.gitnex.actions;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; 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.R;
import org.mian.gitnex.activities.AddCollaboratorToRepositoryActivity; import org.mian.gitnex.activities.AddCollaboratorToRepositoryActivity;
import org.mian.gitnex.clients.RetrofitClient; 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.Authorization;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Permission;
import java.util.List; import java.util.List;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;

View File

@ -3,15 +3,15 @@ package org.mian.gitnex.actions;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.gson.JsonElement; 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.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; 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.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@ -254,7 +254,7 @@ public class IssueActions {
} }
else { else {
Toasty.error(ctx, ctx.getString(R.string.unsubscriptionError)); Toasty.error(ctx, ctx.getString(R.string.unSubscriptionError));
} }

View File

@ -5,13 +5,13 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.Labels;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.adapters.LabelsListAdapter; import org.mian.gitnex.adapters.LabelsListAdapter;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding; import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Labels;
import java.util.List; import java.util.List;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;

View File

@ -4,12 +4,12 @@ import android.content.Context;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import org.gitnex.tea4j.models.Milestones;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Milestones;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;

View File

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

@ -13,12 +13,12 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; 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.adapters.UserSearchAdapter;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityAddCollaboratorToRepositoryBinding;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.models.UserSearch;
import java.util.List; import java.util.List;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -37,23 +37,21 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
private RecyclerView mRecyclerView; private RecyclerView mRecyclerView;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_add_collaborator_to_repository;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityAddCollaboratorToRepositoryBinding activityAddCollaboratorToRepositoryBinding = ActivityAddCollaboratorToRepositoryBinding.inflate(getLayoutInflater());
setContentView(activityAddCollaboratorToRepositoryBinding.getRoot());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = activityAddCollaboratorToRepositoryBinding.close;
addCollaboratorSearch = findViewById(R.id.addCollaboratorSearch); addCollaboratorSearch = activityAddCollaboratorToRepositoryBinding.addCollaboratorSearch;
mRecyclerView = findViewById(R.id.recyclerViewUserSearch); mRecyclerView = activityAddCollaboratorToRepositoryBinding.recyclerViewUserSearch;
mProgressBar = findViewById(R.id.progressBar); mProgressBar = activityAddCollaboratorToRepositoryBinding.progressBar;
noData = findViewById(R.id.noData); noData = activityAddCollaboratorToRepositoryBinding.noData;
addCollaboratorSearch.requestFocus(); addCollaboratorSearch.requestFocus();
assert imm != null; assert imm != null;
@ -83,7 +81,7 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
Call<UserSearch> call = RetrofitClient Call<UserSearch> call = RetrofitClient
.getApiInterface(appCtx) .getApiInterface(appCtx)
.getUserBySearch(Authorization.get(ctx), searchKeyword, 10); .getUserBySearch(Authorization.get(ctx), searchKeyword, 10, 1);
call.enqueue(new Callback<UserSearch>() { call.enqueue(new Callback<UserSearch>() {

View File

@ -8,8 +8,11 @@ import android.view.View;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; 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.R;
import org.mian.gitnex.clients.RetrofitClient; 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.api.UserAccountsApi;
import org.mian.gitnex.databinding.ActivityAddNewAccountBinding; import org.mian.gitnex.databinding.ActivityAddNewAccountBinding;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
@ -17,8 +20,6 @@ import org.mian.gitnex.helpers.PathsHelper;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UrlHelper; import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.models.UserInfo;
import java.net.URI; import java.net.URI;
import io.mikael.urlbuilder.UrlBuilder; import io.mikael.urlbuilder.UrlBuilder;
import retrofit2.Call; import retrofit2.Call;
@ -36,31 +37,24 @@ public class AddNewAccountActivity extends BaseActivity {
private enum Protocol {HTTPS, HTTP} private enum Protocol {HTTPS, HTTP}
private String spinnerSelectedValue; private String spinnerSelectedValue;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_add_new_account;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewBinding = ActivityAddNewAccountBinding.inflate(getLayoutInflater()); viewBinding = ActivityAddNewAccountBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot(); setContentView(viewBinding.getRoot());
setContentView(view);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT)); getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
initCloseListener(); initCloseListener();
viewBinding.close.setOnClickListener(onClickListener); viewBinding.close.setOnClickListener(onClickListener);
viewBinding.instanceUrl.setText(getIntent().getStringExtra("instanceUrl"));
ArrayAdapter<Protocol> adapterProtocols = new ArrayAdapter<>(ctx, R.layout.list_spinner_items, Protocol.values()); ArrayAdapter<Protocol> adapterProtocols = new ArrayAdapter<>(ctx, R.layout.list_spinner_items, Protocol.values());
viewBinding.protocolSpinner.setAdapter(adapterProtocols); viewBinding.protocolSpinner.setAdapter(adapterProtocols);
viewBinding.protocolSpinner.setOnItemClickListener((parent, view1, position, id) -> spinnerSelectedValue = String.valueOf(parent.getItemAtPosition(position))); viewBinding.protocolSpinner.setOnItemClickListener((parent, view1, position, id) -> spinnerSelectedValue = String.valueOf(parent.getItemAtPosition(position)));
viewBinding.addNewAccount.setOnClickListener(login -> { viewBinding.addNewAccount.setOnClickListener(login -> {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
@ -122,9 +116,7 @@ public class AddNewAccountActivity extends BaseActivity {
private void versionCheck(final String instanceUrl, final String loginToken) { private void versionCheck(final String instanceUrl, final String loginToken) {
Call<GiteaVersion> callVersion; Call<GiteaVersion> callVersion;
callVersion = RetrofitClient.getApiInterface(ctx, instanceUrl).getGiteaVersionWithToken("token " + loginToken);
callVersion = RetrofitClient.getApiInterface(ctx).getGiteaVersionWithToken("token " + loginToken);
callVersion.enqueue(new Callback<GiteaVersion>() { callVersion.enqueue(new Callback<GiteaVersion>() {
@Override @Override
@ -151,7 +143,7 @@ public class AddNewAccountActivity extends BaseActivity {
.setMessage(getResources().getString(R.string.versionUnsupportedOld, version.getVersion())).setIcon(R.drawable.ic_warning) .setMessage(getResources().getString(R.string.versionUnsupportedOld, version.getVersion())).setIcon(R.drawable.ic_warning)
.setCancelable(true); .setCancelable(true);
alertDialogBuilder.setNegativeButton(getString(R.string.cancelButton), (dialog, which) -> { alertDialogBuilder.setNeutralButton(getString(R.string.cancelButton), (dialog, which) -> {
dialog.dismiss(); dialog.dismiss();
}); });
@ -213,14 +205,15 @@ public class AddNewAccountActivity extends BaseActivity {
assert userDetails != null; assert userDetails != null;
// insert new account to db if does not exist // insert new account to db if does not exist
String accountName = userDetails.getUsername() + "@" + instanceUrl; String accountName = userDetails.getUsername() + "@" + instanceUrl;
UserAccountsApi userAccountsApi = new UserAccountsApi(ctx); UserAccountsApi userAccountsApi = BaseApi.getInstance(ctx, UserAccountsApi.class);
int checkAccount = userAccountsApi.getCount(accountName); 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)); Toasty.success(ctx, getResources().getString(R.string.accountAddedMessage));
finish(); finish();
} }
else { else {

View File

@ -14,12 +14,12 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; 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.adapters.UserSearchForTeamMemberAdapter;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityAddNewTeamMemberBinding;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.models.UserSearch;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -44,23 +44,21 @@ public class AddNewTeamMemberActivity extends BaseActivity {
private String teamId; private String teamId;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_add_new_team_member;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityAddNewTeamMemberBinding activityAddNewTeamMemberBinding = ActivityAddNewTeamMemberBinding.inflate(getLayoutInflater());
setContentView(activityAddNewTeamMemberBinding.getRoot());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = activityAddNewTeamMemberBinding.close;
addNewTeamMember = findViewById(R.id.addNewTeamMember); addNewTeamMember = activityAddNewTeamMemberBinding.addNewTeamMember;
mRecyclerView = findViewById(R.id.recyclerViewUserSearch); mRecyclerView = activityAddNewTeamMemberBinding.recyclerViewUserSearch;
mProgressBar = findViewById(R.id.progress_bar); mProgressBar = activityAddNewTeamMemberBinding.progressBar;
noData = findViewById(R.id.noData); noData = activityAddNewTeamMemberBinding.noData;
addNewTeamMember.requestFocus(); addNewTeamMember.requestFocus();
assert imm != null; assert imm != null;
@ -112,7 +110,7 @@ public class AddNewTeamMemberActivity extends BaseActivity {
public void loadUserSearchList(String searchKeyword, String teamId) { public void loadUserSearchList(String searchKeyword, String teamId) {
Call<UserSearch> call = RetrofitClient.getApiInterface(ctx).getUserBySearch(Authorization.get(ctx), searchKeyword, 10); Call<UserSearch> call = RetrofitClient.getApiInterface(ctx).getUserBySearch(Authorization.get(ctx), searchKeyword, 10, 1);
mProgressBar.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.VISIBLE);

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,6 +21,7 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.adapters.AdminGetUsersAdapter; import org.mian.gitnex.adapters.AdminGetUsersAdapter;
import org.mian.gitnex.databinding.ActivityAdminGetUsersBinding;
import org.mian.gitnex.fragments.BottomSheetAdminUsersFragment; import org.mian.gitnex.fragments.BottomSheetAdminUsersFragment;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
@ -38,23 +39,21 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
private TextView noDataUsers; private TextView noDataUsers;
private Boolean searchFilter = false; private Boolean searchFilter = false;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_admin_get_users;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ImageView closeActivity = findViewById(R.id.close); ActivityAdminGetUsersBinding activityAdminGetUsersBinding = ActivityAdminGetUsersBinding.inflate(getLayoutInflater());
noDataUsers = findViewById(R.id.noDataUsers); setContentView(activityAdminGetUsersBinding.getRoot());
mRecyclerView = findViewById(R.id.recyclerView);
final SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh); ImageView closeActivity = activityAdminGetUsersBinding.close;
noDataUsers = activityAdminGetUsersBinding.noDataUsers;
mRecyclerView = activityAdminGetUsersBinding.recyclerView;
Toolbar toolbar = findViewById(R.id.toolbar); final SwipeRefreshLayout swipeRefresh = activityAdminGetUsersBinding.pullToRefresh;
Toolbar toolbar = activityAdminGetUsersBinding.toolbar;
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
initCloseListener(); initCloseListener();

View File

@ -1,39 +1,23 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import org.acra.ACRA; import androidx.biometric.BiometricPrompt;
import org.acra.BuildConfig; import androidx.core.content.ContextCompat;
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 org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.FontsOverride;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TimeHelper; import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.notifications.NotificationsMaster; import org.mian.gitnex.notifications.Notifications;
import static org.acra.ReportField.ANDROID_VERSION; import java.util.Locale;
import static org.acra.ReportField.PHONE_MODEL; import java.util.concurrent.Executor;
import static org.acra.ReportField.STACK_TRACE;
/** /**
* Author M M Arif * Author M M Arif
*/ */
@SuppressLint("NonConstantResourceId")
@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 { public abstract class BaseActivity extends AppCompatActivity {
protected TinyDB tinyDB; protected TinyDB tinyDB;
@ -44,6 +28,8 @@ public abstract class BaseActivity extends AppCompatActivity {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.appCtx = getApplicationContext(); this.appCtx = getApplicationContext();
this.tinyDB = TinyDB.getInstance(appCtx); this.tinyDB = TinyDB.getInstance(appCtx);
@ -56,7 +42,7 @@ public abstract class BaseActivity extends AppCompatActivity {
break; break;
case 2: 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"); tinyDB.putString("currentTheme", "dark");
setTheme(R.style.AppTheme); setTheme(R.style.AppTheme);
@ -73,7 +59,7 @@ public abstract class BaseActivity extends AppCompatActivity {
setTheme(R.style.AppThemeRetro); setTheme(R.style.AppThemeRetro);
break; break;
case 4: 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"); tinyDB.putString("currentTheme", "dark");
setTheme(R.style.AppTheme); setTheme(R.style.AppTheme);
@ -96,89 +82,55 @@ public abstract class BaseActivity extends AppCompatActivity {
} }
String appLocale = tinyDB.getString("locale"); String locale = tinyDB.getString("locale");
AppUtil.setAppLocale(getResources(), appLocale); if (locale.isEmpty()) {
AppUtil.setAppLocale(getResources(), Locale.getDefault().getLanguage());
super.onCreate(savedInstanceState); }
setContentView(getLayoutResourceId()); else {
AppUtil.setAppLocale(getResources(), locale);
// FIXME Performance nightmare
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");
} }
if(tinyDB.getInt("pollingDelayMinutes", 0) <= 0) { Notifications.startWorker(appCtx);
tinyDB.putInt("pollingDelayMinutes", StaticGlobalVariables.defaultPollingDelay);
} }
// FIXME Performance nightmare public void onResume() {
NotificationsMaster.hireWorker(appCtx); super.onResume();
// enabling counter badges by default if(tinyDB.getBoolean("biometricStatus") && !tinyDB.getBoolean("biometricLifeCycle")) {
if(tinyDB.getString("enableCounterBadgesInit").isEmpty()) {
tinyDB.putBoolean("enableCounterBadges", true); Executor executor = ContextCompat.getMainExecutor(this);
tinyDB.putString("enableCounterBadgesInit", "yes");
}
// enable crash reports by default BiometricPrompt biometricPrompt = new BiometricPrompt(this, executor, new BiometricPrompt.AuthenticationCallback() {
if(tinyDB.getString("crashReportingEnabledInit").isEmpty()) {
tinyDB.putBoolean("crashReportingEnabled", true); @Override
tinyDB.putString("crashReportingEnabledInit", "yes"); public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
}
// default cache setter super.onAuthenticationError(errorCode, errString);
if(tinyDB.getString("cacheSizeStr").isEmpty()) {
tinyDB.putString("cacheSizeStr", getResources().getString(R.string.cacheSizeDataSelectionSelectedText)); // Authentication error, close the app
} if(errorCode == BiometricPrompt.ERROR_USER_CANCELED ||
if(tinyDB.getString("cacheSizeImagesStr").isEmpty()) { errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) {
finish();
tinyDB.putString("cacheSizeImagesStr", getResources().getString(R.string.cacheSizeImagesSelectionSelectedText));
}
// enable comment drafts by default
if(tinyDB.getString("draftsCommentsDeletionEnabledInit").isEmpty()) {
tinyDB.putBoolean("draftsCommentsDeletionEnabled", true);
tinyDB.putString("draftsCommentsDeletionEnabledInit", "yes");
}
// FIXME Performance nightmare
if (tinyDB.getBoolean("crashReportingEnabled")) {
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);
} }
} }
protected abstract int getLayoutResourceId(); // 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);
}
}
} }

View File

@ -18,14 +18,15 @@ import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.gitnex.tea4j.models.Commits;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.adapters.CommitsAdapter; import org.mian.gitnex.adapters.CommitsAdapter;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCommitsBinding;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables; import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Commits;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import retrofit2.Call; import retrofit2.Call;
@ -42,7 +43,7 @@ public class CommitsActivity extends BaseActivity {
private TextView noData; private TextView noData;
private ProgressBar progressBar; private ProgressBar progressBar;
private String TAG = "CommitsActivity"; private String TAG = "CommitsActivity";
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
private int pageSize = 1; private int pageSize = 1;
private RecyclerView recyclerView; private RecyclerView recyclerView;
@ -50,17 +51,15 @@ public class CommitsActivity extends BaseActivity {
private CommitsAdapter adapter; private CommitsAdapter adapter;
private ProgressBar progressLoadMore; private ProgressBar progressLoadMore;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_commits;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Toolbar toolbar = findViewById(R.id.toolbar);
ActivityCommitsBinding activityCommitsBinding = ActivityCommitsBinding.inflate(getLayoutInflater());
setContentView(activityCommitsBinding.getRoot());
Toolbar toolbar = activityCommitsBinding.toolbar;
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
String repoFullName = tinyDB.getString("repoFullName"); String repoFullName = tinyDB.getString("repoFullName");
@ -70,15 +69,15 @@ public class CommitsActivity extends BaseActivity {
String branchName = getIntent().getStringExtra("branchName"); 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.setMovementMethod(new ScrollingMovementMethod());
toolbar_title.setText(branchName); toolbar_title.setText(branchName);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = activityCommitsBinding.close;
noData = findViewById(R.id.noDataCommits); noData = activityCommitsBinding.noDataCommits;
progressLoadMore = findViewById(R.id.progressLoadMore); progressLoadMore = activityCommitsBinding.progressLoadMore;
progressBar = findViewById(R.id.progress_bar); progressBar = activityCommitsBinding.progressBar;
SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh); SwipeRefreshLayout swipeRefresh = activityCommitsBinding.pullToRefresh;
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
@ -86,10 +85,10 @@ public class CommitsActivity extends BaseActivity {
// if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances) // if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances)
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12")) { if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances; resultLimit = Constants.resultLimitNewGiteaInstances;
} }
recyclerView = findViewById(R.id.recyclerView); recyclerView = activityCommitsBinding.recyclerView;
commitsList = new ArrayList<>(); commitsList = new ArrayList<>();
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> { swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {

View File

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

View File

@ -14,6 +14,10 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.gson.JsonElement; 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.R;
import org.mian.gitnex.actions.AssigneesActions; import org.mian.gitnex.actions.AssigneesActions;
import org.mian.gitnex.actions.LabelsActions; import org.mian.gitnex.actions.LabelsActions;
@ -26,14 +30,10 @@ import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; 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.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; 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.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
@ -51,7 +51,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private CustomLabelsSelectionDialogBinding labelsBinding; private CustomLabelsSelectionDialogBinding labelsBinding;
private CustomAssigneesSelectionDialogBinding assigneesBinding; private CustomAssigneesSelectionDialogBinding assigneesBinding;
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
private Dialog dialogLabels; private Dialog dialogLabels;
private Dialog dialogAssignees; private Dialog dialogAssignees;
private String labelsSetter; private String labelsSetter;
@ -71,11 +71,6 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private List<Collaborators> assigneesList = new ArrayList<>(); private List<Collaborators> assigneesList = new ArrayList<>();
private List<String> assigneesListData = new ArrayList<>(); private List<String> assigneesListData = new ArrayList<>();
@Override
protected int getLayoutResourceId() {
return R.layout.activity_create_issue;
}
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -83,8 +78,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewBinding = ActivityCreateIssueBinding.inflate(getLayoutInflater()); viewBinding = ActivityCreateIssueBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot(); setContentView(viewBinding.getRoot());
setContentView(view);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
@ -99,7 +93,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
// require gitea 1.12 or higher // 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(); viewBinding.newIssueTitle.requestFocus();

View File

@ -13,15 +13,16 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import com.pes.androidmaterialcolorpickerdialog.ColorPicker; import com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import org.gitnex.tea4j.models.CreateLabel;
import org.gitnex.tea4j.models.Labels;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateLabelBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; 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.LabelsViewModel;
import org.mian.gitnex.viewmodels.OrganizationLabelsViewModel; import org.mian.gitnex.viewmodels.OrganizationLabelsViewModel;
import java.util.Objects; import java.util.Objects;
@ -40,16 +41,14 @@ public class CreateLabelActivity extends BaseActivity {
private Button createLabelButton; private Button createLabelButton;
private TinyDB tinyDB; private TinyDB tinyDB;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_label;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityCreateLabelBinding activityCreateLabelBinding = ActivityCreateLabelBinding.inflate(getLayoutInflater());
setContentView(activityCreateLabelBinding.getRoot());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
tinyDB = TinyDB.getInstance(appCtx); tinyDB = TinyDB.getInstance(appCtx);
@ -67,10 +66,10 @@ public class CreateLabelActivity extends BaseActivity {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = activityCreateLabelBinding.close;
colorPicker = findViewById(R.id.colorPicker); colorPicker = activityCreateLabelBinding.colorPicker;
labelName = findViewById(R.id.labelName); labelName = activityCreateLabelBinding.labelName;
createLabelButton = findViewById(R.id.createLabelButton); createLabelButton = activityCreateLabelBinding.createLabelButton;
labelName.requestFocus(); labelName.requestFocus();
assert imm != null; assert imm != null;
@ -97,7 +96,7 @@ public class CreateLabelActivity extends BaseActivity {
colorPicker.setBackgroundColor(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)); toolbar_title.setText(getResources().getString(R.string.pageTitleLabelUpdate));
createLabelButton.setText(getResources().getString(R.string.newUpdateButtonCopy)); createLabelButton.setText(getResources().getString(R.string.newUpdateButtonCopy));
@ -123,7 +122,7 @@ public class CreateLabelActivity extends BaseActivity {
private void processUpdateLabel() { private void processUpdateLabel() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
String repoFullName = tinyDB.getString("repoFullName"); String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
final String repoOwner = parts[0]; final String repoOwner = parts[0];
@ -153,7 +152,7 @@ public class CreateLabelActivity extends BaseActivity {
return; return;
} }
if(!appUtil.checkStrings(updateLabelName)) { if(!AppUtil.checkStrings(updateLabelName)) {
Toasty.error(ctx, getString(R.string.labelNameError)); Toasty.error(ctx, getString(R.string.labelNameError));
return; return;
@ -168,7 +167,6 @@ public class CreateLabelActivity extends BaseActivity {
private void processCreateLabel() { private void processCreateLabel() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
String repoFullName = tinyDB.getString("repoFullName"); String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
@ -199,7 +197,7 @@ public class CreateLabelActivity extends BaseActivity {
return; return;
} }
if(!appUtil.checkStrings(newLabelName)) { if(!AppUtil.checkStrings(newLabelName)) {
Toasty.error(ctx, getString(R.string.labelNameError)); Toasty.error(ctx, getString(R.string.labelNameError));
return; return;

View File

@ -12,15 +12,16 @@ import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.Milestones;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateMilestoneBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Milestones;
import java.util.Calendar; import java.util.Calendar;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -37,26 +38,24 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
private EditText milestoneDescription; private EditText milestoneDescription;
private Button createNewMilestoneButton; private Button createNewMilestoneButton;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_milestone;
}
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityCreateMilestoneBinding activityCreateMilestoneBinding = ActivityCreateMilestoneBinding.inflate(getLayoutInflater());
setContentView(activityCreateMilestoneBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
milestoneDueDate = findViewById(R.id.milestoneDueDate); milestoneDueDate = activityCreateMilestoneBinding.milestoneDueDate;
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = activityCreateMilestoneBinding.close;
createNewMilestoneButton = findViewById(R.id.createNewMilestoneButton); createNewMilestoneButton = activityCreateMilestoneBinding.createNewMilestoneButton;
milestoneTitle = findViewById(R.id.milestoneTitle); milestoneTitle = activityCreateMilestoneBinding.milestoneTitle;
milestoneDescription = findViewById(R.id.milestoneDescription); milestoneDescription = activityCreateMilestoneBinding.milestoneDescription;
milestoneTitle.requestFocus(); milestoneTitle.requestFocus();
assert imm != null; assert imm != null;
@ -93,7 +92,7 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
private void processNewMilestone() { private void processNewMilestone() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = TinyDB.getInstance(appCtx); TinyDB tinyDb = TinyDB.getInstance(appCtx);
String repoFullName = tinyDb.getString("repoFullName"); String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
@ -118,7 +117,7 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
if(!newMilestoneDescription.equals("")) { if(!newMilestoneDescription.equals("")) {
if (appUtil.charactersLength(newMilestoneDescription) > 255) { if (newMilestoneDescription.length() > 255) {
Toasty.warning(ctx, getString(R.string.milestoneDescError)); Toasty.warning(ctx, getString(R.string.milestoneDescError));
return; return;

View File

@ -10,14 +10,14 @@ import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateNewUserBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserInfo;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -34,26 +34,24 @@ public class CreateNewUserActivity extends BaseActivity {
private EditText userPassword; private EditText userPassword;
private Button createUserButton; private Button createUserButton;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_new_user;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityCreateNewUserBinding activityCreateNewUserBinding = ActivityCreateNewUserBinding.inflate(getLayoutInflater());
setContentView(activityCreateNewUserBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = activityCreateNewUserBinding.close;
createUserButton = findViewById(R.id.createUserButton); createUserButton = activityCreateNewUserBinding.createUserButton;
fullName = findViewById(R.id.fullName); fullName = activityCreateNewUserBinding.fullName;
userUserName = findViewById(R.id.userUserName); userUserName = activityCreateNewUserBinding.userUserName;
userEmail = findViewById(R.id.userEmail); userEmail = activityCreateNewUserBinding.userEmail;
userPassword = findViewById(R.id.userPassword); userPassword = activityCreateNewUserBinding.userPassword;
fullName.requestFocus(); fullName.requestFocus();
assert imm != null; assert imm != null;
@ -75,8 +73,6 @@ public class CreateNewUserActivity extends BaseActivity {
private void processCreateNewUser() { private void processCreateNewUser() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = TinyDB.getInstance(appCtx);
String newFullName = fullName.getText().toString().trim(); String newFullName = fullName.getText().toString().trim();
String newUserName = userUserName.getText().toString().trim(); String newUserName = userUserName.getText().toString().trim();
@ -95,13 +91,13 @@ public class CreateNewUserActivity extends BaseActivity {
return; return;
} }
if(!appUtil.checkStrings(newFullName)) { if(!AppUtil.checkStrings(newFullName)) {
Toasty.error(ctx, getString(R.string.userInvalidFullName)); Toasty.error(ctx, getString(R.string.userInvalidFullName));
return; return;
} }
if(!appUtil.checkStringsWithAlphaNumeric(newUserName)) { if(!AppUtil.checkStringsWithAlphaNumeric(newUserName)) {
Toasty.error(ctx, getString(R.string.userInvalidUserName)); Toasty.error(ctx, getString(R.string.userInvalidUserName));
return; return;

View File

@ -11,14 +11,15 @@ import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.gitnex.tea4j.models.UserOrganizations;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateOrganizationBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserOrganizations;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -35,24 +36,22 @@ public class CreateOrganizationActivity extends BaseActivity {
private EditText orgName; private EditText orgName;
private EditText orgDesc; private EditText orgDesc;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_organization;
}
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityCreateOrganizationBinding activityCreateOrganizationBinding = ActivityCreateOrganizationBinding.inflate(getLayoutInflater());
setContentView(activityCreateOrganizationBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
closeActivity = findViewById(R.id.close); closeActivity = activityCreateOrganizationBinding.close;
orgName = findViewById(R.id.newOrganizationName); orgName = activityCreateOrganizationBinding.newOrganizationName;
orgDesc = findViewById(R.id.newOrganizationDescription); orgDesc = activityCreateOrganizationBinding.newOrganizationDescription;
orgName.requestFocus(); orgName.requestFocus();
assert imm != null; assert imm != null;
@ -72,7 +71,7 @@ public class CreateOrganizationActivity extends BaseActivity {
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
createOrganizationButton = findViewById(R.id.createNewOrganizationButton); createOrganizationButton = activityCreateOrganizationBinding.createNewOrganizationButton;
if(!connToInternet) { if(!connToInternet) {
@ -95,8 +94,6 @@ public class CreateOrganizationActivity extends BaseActivity {
private void processNewOrganization() { private void processNewOrganization() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = TinyDB.getInstance(appCtx);
String newOrgName = orgName.getText().toString(); String newOrgName = orgName.getText().toString();
String newOrgDesc = orgDesc.getText().toString(); String newOrgDesc = orgDesc.getText().toString();
@ -109,7 +106,7 @@ public class CreateOrganizationActivity extends BaseActivity {
if(!newOrgDesc.equals("")) { if(!newOrgDesc.equals("")) {
if (appUtil.charactersLength(newOrgDesc) > 255) { if (newOrgDesc.length() > 255) {
Toasty.warning(ctx, getString(R.string.orgDescError)); Toasty.warning(ctx, getString(R.string.orgDescError));
return; return;
@ -120,7 +117,7 @@ public class CreateOrganizationActivity extends BaseActivity {
Toasty.error(ctx, getString(R.string.orgNameErrorEmpty)); Toasty.error(ctx, getString(R.string.orgNameErrorEmpty));
} }
else if(!appUtil.checkStrings(newOrgName)) { else if(!AppUtil.checkStrings(newOrgName)) {
Toasty.warning(ctx, getString(R.string.orgNameErrorInvalid)); Toasty.warning(ctx, getString(R.string.orgNameErrorInvalid));
} }

View File

@ -12,6 +12,10 @@ import android.view.View;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull; 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.R;
import org.mian.gitnex.actions.LabelsActions; import org.mian.gitnex.actions.LabelsActions;
import org.mian.gitnex.adapters.LabelsListAdapter; import org.mian.gitnex.adapters.LabelsListAdapter;
@ -20,17 +24,12 @@ import org.mian.gitnex.databinding.ActivityCreatePrBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding; import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables; import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; 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.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -43,7 +42,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private ActivityCreatePrBinding viewBinding; private ActivityCreatePrBinding viewBinding;
private CustomLabelsSelectionDialogBinding labelsBinding; private CustomLabelsSelectionDialogBinding labelsBinding;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
private Dialog dialogLabels; private Dialog dialogLabels;
private String labelsSetter; private String labelsSetter;
private List<Integer> labelsIds = new ArrayList<>(); private List<Integer> labelsIds = new ArrayList<>();
@ -61,14 +60,6 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
List<Branches> branchesList = new ArrayList<>(); List<Branches> branchesList = new ArrayList<>();
List<Labels> labelsList = new ArrayList<>(); List<Labels> labelsList = new ArrayList<>();
public CreatePullRequestActivity() {
}
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_pr;
}
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -76,8 +67,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewBinding = ActivityCreatePrBinding.inflate(getLayoutInflater()); viewBinding = ActivityCreatePrBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot(); setContentView(viewBinding.getRoot());
setContentView(view);
loginUid = tinyDB.getString("loginUid"); loginUid = tinyDB.getString("loginUid");
String repoFullName = tinyDB.getString("repoFullName"); String repoFullName = tinyDB.getString("repoFullName");
@ -89,7 +79,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
// require gitea 1.12 or higher // 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.prBody.setOnTouchListener((touchView, motionEvent) -> { viewBinding.prBody.setOnTouchListener((touchView, motionEvent) -> {
@ -174,14 +164,14 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
CreatePullRequest createPullRequest = new CreatePullRequest(prTitle, prDescription, loginUid, mergeInto, pullFrom, milestoneId, dueDate, assignees, labelsIds); CreatePullRequest createPullRequest = new CreatePullRequest(prTitle, prDescription, loginUid, mergeInto, pullFrom, milestoneId, dueDate, assignees, labelsIds);
Call<ResponseBody> transferCall = RetrofitClient Call<Void> transferCall = RetrofitClient
.getApiInterface(appCtx) .getApiInterface(appCtx)
.createPullRequest(instanceToken, repoOwner, repoName, createPullRequest); .createPullRequest(instanceToken, repoOwner, repoName, createPullRequest);
transferCall.enqueue(new Callback<ResponseBody>() { transferCall.enqueue(new Callback<Void>() {
@Override @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(); disableProcessButton();
@ -208,7 +198,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
} }
@Override @Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, getString(R.string.genericServerResponseError)); Toasty.error(ctx, getString(R.string.genericServerResponseError));

View File

@ -14,14 +14,15 @@ import android.widget.CheckBox;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull; 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.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateReleaseBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty; 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.ArrayList;
import java.util.List; import java.util.List;
import retrofit2.Call; import retrofit2.Call;
@ -49,17 +50,15 @@ public class CreateReleaseActivity extends BaseActivity {
List<Branches> branchesList = new ArrayList<>(); List<Branches> branchesList = new ArrayList<>();
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_release;
}
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityCreateReleaseBinding activityCreateReleaseBinding = ActivityCreateReleaseBinding.inflate(getLayoutInflater());
setContentView(activityCreateReleaseBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -69,12 +68,12 @@ public class CreateReleaseActivity extends BaseActivity {
repoOwner = parts[0]; repoOwner = parts[0];
repoName = parts[1]; repoName = parts[1];
closeActivity = findViewById(R.id.close); closeActivity = activityCreateReleaseBinding.close;
releaseTagName = findViewById(R.id.releaseTagName); releaseTagName = activityCreateReleaseBinding.releaseTagName;
releaseTitle = findViewById(R.id.releaseTitle); releaseTitle = activityCreateReleaseBinding.releaseTitle;
releaseContent = findViewById(R.id.releaseContent); releaseContent = activityCreateReleaseBinding.releaseContent;
releaseType = findViewById(R.id.releaseType); releaseType = activityCreateReleaseBinding.releaseType;
releaseDraft = findViewById(R.id.releaseDraft); releaseDraft = activityCreateReleaseBinding.releaseDraft;
releaseTitle.requestFocus(); releaseTitle.requestFocus();
assert imm != null; assert imm != null;
@ -94,10 +93,10 @@ public class CreateReleaseActivity extends BaseActivity {
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
releaseBranch = findViewById(R.id.releaseBranch); releaseBranch = activityCreateReleaseBinding.releaseBranch;
getBranches(Authorization.get(ctx), repoOwner, repoName); getBranches(Authorization.get(ctx), repoOwner, repoName);
createNewRelease = findViewById(R.id.createNewRelease); createNewRelease = activityCreateReleaseBinding.createNewRelease;
disableProcessButton(); disableProcessButton();
if(!connToInternet) { if(!connToInternet) {

View File

@ -14,15 +14,16 @@ import android.widget.CheckBox;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull; 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.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateRepoBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; 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.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -55,16 +56,14 @@ public class CreateRepoActivity extends BaseActivity {
final List<String> reservedRepoNames = Arrays.asList(".", ".."); final List<String> reservedRepoNames = Arrays.asList(".", "..");
final Pattern reservedRepoPatterns = Pattern.compile("\\.(git|wiki)$"); final Pattern reservedRepoPatterns = Pattern.compile("\\.(git|wiki)$");
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_repo;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityCreateRepoBinding activityCreateRepoBinding = ActivityCreateRepoBinding.inflate(getLayoutInflater());
setContentView(activityCreateRepoBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(ctx); boolean connToInternet = AppUtil.hasNetworkConnection(ctx);
loginUid = tinyDB.getString("loginUid"); loginUid = tinyDB.getString("loginUid");
@ -72,10 +71,10 @@ public class CreateRepoActivity extends BaseActivity {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
closeActivity = findViewById(R.id.close); closeActivity = activityCreateRepoBinding.close;
repoName = findViewById(R.id.newRepoName); repoName = activityCreateRepoBinding.newRepoName;
repoDesc = findViewById(R.id.newRepoDescription); repoDesc = activityCreateRepoBinding.newRepoDescription;
repoAccess = findViewById(R.id.newRepoPrivate); repoAccess = activityCreateRepoBinding.newRepoPrivate;
repoName.requestFocus(); repoName.requestFocus();
assert imm != null; assert imm != null;
@ -84,10 +83,10 @@ public class CreateRepoActivity extends BaseActivity {
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
spinner = findViewById(R.id.ownerSpinner); spinner = activityCreateRepoBinding.ownerSpinner;
getOrganizations(Authorization.get(ctx), userLogin); getOrganizations(Authorization.get(ctx), userLogin);
createRepo = findViewById(R.id.createNewRepoButton); createRepo = activityCreateRepoBinding.createNewRepoButton;
disableProcessButton(); disableProcessButton();
if(!connToInternet) { if(!connToInternet) {
@ -105,7 +104,6 @@ public class CreateRepoActivity extends BaseActivity {
private void processNewRepo() { private void processNewRepo() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
String newRepoName = repoName.getText().toString(); String newRepoName = repoName.getText().toString();
String newRepoDesc = repoDesc.getText().toString(); String newRepoDesc = repoDesc.getText().toString();
@ -119,7 +117,7 @@ public class CreateRepoActivity extends BaseActivity {
if(!newRepoDesc.equals("")) { if(!newRepoDesc.equals("")) {
if (appUtil.charactersLength(newRepoDesc) > 255) { if (newRepoDesc.length() > 255) {
Toasty.warning(ctx, getString(R.string.repoDescError)); Toasty.warning(ctx, getString(R.string.repoDescError));
return; return;
@ -130,7 +128,7 @@ public class CreateRepoActivity extends BaseActivity {
Toasty.error(ctx, getString(R.string.repoNameErrorEmpty)); Toasty.error(ctx, getString(R.string.repoNameErrorEmpty));
} }
else if(!appUtil.checkStrings(newRepoName)) { else if(!AppUtil.checkStrings(newRepoName)) {
Toasty.warning(ctx, getString(R.string.repoNameErrorInvalid)); Toasty.warning(ctx, getString(R.string.repoNameErrorInvalid));
} }
@ -217,7 +215,7 @@ public class CreateRepoActivity extends BaseActivity {
Call<List<OrgOwner>> call = RetrofitClient Call<List<OrgOwner>> call = RetrofitClient
.getApiInterface(ctx) .getApiInterface(ctx)
.getOrgOwners(instanceToken); .getOrgOwners(instanceToken, 1, 50);
call.enqueue(new Callback<List<OrgOwner>>() { call.enqueue(new Callback<List<OrgOwner>>() {

View File

@ -11,14 +11,16 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; 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.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateTeamByOrgBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Teams;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -42,11 +44,6 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
private final String[] permissionList = {"Read", "Write", "Admin"}; private final String[] permissionList = {"Read", "Write", "Admin"};
public int permissionSelectedChoice = -1; public int permissionSelectedChoice = -1;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_team_by_org;
}
private final String[] accessControlsList = new String[] { private final String[] accessControlsList = new String[] {
"Code", "Code",
"Issues", "Issues",
@ -74,18 +71,21 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityCreateTeamByOrgBinding activityCreateTeamByOrgBinding = ActivityCreateTeamByOrgBinding.inflate(getLayoutInflater());
setContentView(activityCreateTeamByOrgBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = activityCreateTeamByOrgBinding.close;
teamName = findViewById(R.id.teamName); teamName = activityCreateTeamByOrgBinding.teamName;
teamDesc = findViewById(R.id.teamDesc); teamDesc = activityCreateTeamByOrgBinding.teamDesc;
teamPermission = findViewById(R.id.teamPermission); teamPermission = activityCreateTeamByOrgBinding.teamPermission;
teamPermissionDetail = findViewById(R.id.teamPermissionDetail); teamPermissionDetail = activityCreateTeamByOrgBinding.teamPermissionDetail;
teamAccessControls = findViewById(R.id.teamAccessControls); teamAccessControls = activityCreateTeamByOrgBinding.teamAccessControls;
teamAccessControlsArray = findViewById(R.id.teamAccessControlsArray); teamAccessControlsArray = activityCreateTeamByOrgBinding.teamAccessControlsArray;
createTeamButton = findViewById(R.id.createTeamButton); createTeamButton = activityCreateTeamByOrgBinding.createTeamButton;
teamName.requestFocus(); teamName.requestFocus();
assert imm != null; assert imm != null;
@ -211,8 +211,8 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
createTeamButton.setEnabled(false); createTeamButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable(); GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 ); shape.setCornerRadius(8);
shape.setColor(getResources().getColor(R.color.hintColor)); shape.setColor(ResourcesCompat.getColor(getResources(), R.color.hintColor, null));
createTeamButton.setBackground(shape); createTeamButton.setBackground(shape);
} }
else { else {
@ -224,7 +224,6 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
private void processCreateTeam() { private void processCreateTeam() {
AppUtil appUtil = new AppUtil();
final TinyDB tinyDb = TinyDB.getInstance(appCtx); final TinyDB tinyDb = TinyDB.getInstance(appCtx);
final String loginUid = tinyDb.getString("loginUid"); final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
@ -248,7 +247,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
return; return;
} }
if(!appUtil.checkStringsWithAlphaNumericDashDotUnderscore(newTeamName)) { if(!AppUtil.checkStringsWithAlphaNumericDashDotUnderscore(newTeamName)) {
Toasty.warning(ctx, getString(R.string.teamNameError)); Toasty.warning(ctx, getString(R.string.teamNameError));
return; return;
@ -256,7 +255,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
if(!newTeamDesc.equals("")) { if(!newTeamDesc.equals("")) {
if(!appUtil.checkStrings(newTeamDesc)) { if(!AppUtil.checkStrings(newTeamDesc)) {
Toasty.warning(ctx, getString(R.string.teamDescError)); Toasty.warning(ctx, getString(R.string.teamDescError));
return; return;

View File

@ -9,22 +9,31 @@ import android.util.Log;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.apache.commons.lang3.StringUtils; 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.R;
import org.mian.gitnex.clients.RetrofitClient; 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.RepositoriesApi;
import org.mian.gitnex.database.api.UserAccountsApi; import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.Repository; import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.database.models.UserAccount; import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.databinding.ActivityDeeplinksBinding; import org.mian.gitnex.databinding.ActivityDeeplinksBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.UrlHelper; import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.models.PullRequests;
import org.mian.gitnex.models.UserRepositories;
import java.net.URI; import java.net.URI;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import io.mikael.urlbuilder.UrlBuilder; import io.mikael.urlbuilder.UrlBuilder;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response;
/** /**
* Author M M Arif * Author M M Arif
@ -40,12 +49,8 @@ public class DeepLinksActivity extends BaseActivity {
private Intent mainIntent; private Intent mainIntent;
private Intent issueIntent; private Intent issueIntent;
private Intent repoIntent; private Intent repoIntent;
private Intent orgIntent;
@Override private Intent userIntent;
protected int getLayoutResourceId() {
return R.layout.activity_deeplinks;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -53,12 +58,13 @@ public class DeepLinksActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewBinding = ActivityDeeplinksBinding.inflate(getLayoutInflater()); viewBinding = ActivityDeeplinksBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot(); setContentView(viewBinding.getRoot());
setContentView(view);
mainIntent = new Intent(ctx, MainActivity.class); mainIntent = new Intent(ctx, MainActivity.class);
issueIntent = new Intent(ctx, IssueDetailActivity.class); issueIntent = new Intent(ctx, IssueDetailActivity.class);
repoIntent = new Intent(ctx, RepoDetailActivity.class); repoIntent = new Intent(ctx, RepoDetailActivity.class);
orgIntent = new Intent(ctx, OrganizationDetailActivity.class);
userIntent = new Intent(ctx, ProfileActivity.class);
Intent intent = getIntent(); Intent intent = getIntent();
Uri data = intent.getData(); Uri data = intent.getData();
@ -66,13 +72,14 @@ public class DeepLinksActivity extends BaseActivity {
// check for login // 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(); finish();
ctx.startActivity(new Intent(ctx, LoginActivity.class));
} }
// check for the links(URI) to be in the db // 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(); List<UserAccount> userAccounts = userAccountsApi.usersAccounts();
for(UserAccount userAccount : userAccounts) { for(UserAccount userAccount : userAccounts) {
@ -85,34 +92,95 @@ public class DeepLinksActivity extends BaseActivity {
if(hostUri.toLowerCase().contains(Objects.requireNonNull(data.getHost().toLowerCase()))) { if(hostUri.toLowerCase().contains(Objects.requireNonNull(data.getHost().toLowerCase()))) {
accountFound = true; accountFound = true;
AppUtil.switchToAccount(ctx, userAccount);
break; break;
} }
} }
if(accountFound) { 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 // 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) { if(data.getPathSegments().size() == 1) {
if(data.getLastPathSegment().equals("notifications")) { // notifications
viewBinding.progressBar.setVisibility(View.GONE); mainIntent.putExtra("launchFragmentByLinkHandler", "notification");
String[] restOfUrl = Objects.requireNonNull(data.getPath()).split("/"); ctx.startActivity(mainIntent);
finish();
if(data.getPathSegments().contains("issues")) { // issue }
else if(data.getLastPathSegment().equals("explore")) { // explore
mainIntent.putExtra("launchFragmentByLinkHandler", "explore");
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 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
if(!Objects.requireNonNull(data.getLastPathSegment()).contains("issues") & StringUtils.isNumeric(data.getLastPathSegment())) { if(!Objects.requireNonNull(data.getLastPathSegment()).contains("issues") & StringUtils.isNumeric(data.getLastPathSegment())) {
issueIntent.putExtra("issueNumber", data.getLastPathSegment()); 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("issueNumber", data.getLastPathSegment());
tinyDB.putString("issueType", "Issue"); tinyDB.putString("issueType", "Issue");
tinyDB.putString("repoFullName", restOfUrl[restOfUrl.length - 4] + "/" + restOfUrl[restOfUrl.length - 3]); tinyDB.putString("repoFullName", data.getPathSegments().get(0) + "/" + data.getPathSegments().get(1));
final String repoOwner = restOfUrl[restOfUrl.length - 4]; final String repoOwner = data.getPathSegments().get(0);
final String repoName = restOfUrl[restOfUrl.length - 3]; final String repoName = data.getPathSegments().get(1);
int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId"); int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx); RepositoriesApi repositoryData = BaseApi.getInstance(ctx, RepositoriesApi.class);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName); Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
@ -131,125 +199,122 @@ public class DeepLinksActivity extends BaseActivity {
finish(); finish();
} }
else if(Objects.requireNonNull(data.getLastPathSegment()).contains("issues")) { else if(Objects.requireNonNull(data.getLastPathSegment()).contains("issues")) {
new Handler(Looper.getMainLooper()).postDelayed(() ->
new Handler(Looper.getMainLooper()).postDelayed(() -> { goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "issue"), 500);
}
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 3], restOfUrl[restOfUrl.length - 2], "issue"); else if(data.getLastPathSegment().equals("new")) {
}, 500); new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "issueNew"), 500);
} }
else { else {
ctx.startActivity(mainIntent); ctx.startActivity(mainIntent);
finish(); finish();
} }
} }
else if(data.getPathSegments().contains("pulls")) { // pr else if(data.getPathSegments().get(2).equals("pulls")) { // pr
if(!Objects.requireNonNull(data.getLastPathSegment()).contains("pulls") & StringUtils.isNumeric(data.getLastPathSegment())) { if(!Objects.requireNonNull(data.getLastPathSegment()).contains("pulls") & StringUtils.isNumeric(data.getLastPathSegment())) {
new Handler(Looper.getMainLooper()).postDelayed(() -> { new Handler(Looper.getMainLooper()).postDelayed(() -> {
getPullRequest(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 4], restOfUrl[restOfUrl.length - 3], Integer.parseInt(data.getLastPathSegment())); 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); }, 500);
} }
else if(Objects.requireNonNull(data.getLastPathSegment()).contains("pulls")) { 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(() -> { new Handler(Looper.getMainLooper()).postDelayed(() -> {
issueIntent.putExtra("openPrDiff", "true");
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 3], restOfUrl[restOfUrl.length - 2], "pull"); getPullRequest(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), Integer.parseInt(data.getPathSegments().get(3)));
}, 500); }, 500);
} }
else { else {
ctx.startActivity(mainIntent); ctx.startActivity(mainIntent);
finish(); finish();
} }
} }
else if(data.getPathSegments().contains("commit")) { // commits (no API yet to properly implement)
new Handler(Looper.getMainLooper()).postDelayed(() -> { else if(data.getPathSegments().get(2).equals("compare")) { // new pull request
new Handler(Looper.getMainLooper()).postDelayed(() ->
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 4], restOfUrl[restOfUrl.length - 3], "pull"); goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "pullNew"), 500);
}, 500);
} }
else if(!restOfUrl[restOfUrl.length - 2].equals("") & !restOfUrl[restOfUrl.length - 1].equals("")) { // go to repo else if(data.getPathSegments().get(2).equals("commit")) { // commits (no API yet to properly implement)
new Handler(Looper.getMainLooper()).postDelayed(() ->
new Handler(Looper.getMainLooper()).postDelayed(() -> { goToRepoSection(currentInstance, instanceToken, data.getPathSegments().get(0), data.getPathSegments().get(1), "pull"), 500);
}
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 2], restOfUrl[restOfUrl.length - 1], "repo"); else if(data.getPathSegments().get(2).equals("commits")) { // commits list
}, 500); 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 else { // no action, show options
showNoActionButtons();
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();
});
}
} }
} }
else { else {
@ -268,6 +333,7 @@ public class DeepLinksActivity extends BaseActivity {
viewBinding.addNewAccount.setOnClickListener(addNewAccount -> { viewBinding.addNewAccount.setOnClickListener(addNewAccount -> {
Intent accountIntent = new Intent(ctx, AddNewAccountActivity.class); Intent accountIntent = new Intent(ctx, AddNewAccountActivity.class);
accountIntent.putExtra("instanceUrl", data.getHost());
startActivity(accountIntent); startActivity(accountIntent);
finish(); finish();
}); });
@ -318,6 +384,7 @@ public class DeepLinksActivity extends BaseActivity {
issueIntent.putExtra("issueNumber", index); issueIntent.putExtra("issueNumber", index);
issueIntent.putExtra("prMergeable", prInfo.isMergeable()); issueIntent.putExtra("prMergeable", prInfo.isMergeable());
issueIntent.putExtra("openedFromLink", "true");
if(prInfo.getHead() != null) { if(prInfo.getHead() != null) {
@ -333,7 +400,7 @@ public class DeepLinksActivity extends BaseActivity {
// pull was done from a deleted fork // pull was done from a deleted fork
tinyDB.putString("prIsFork", "true"); tinyDB.putString("prIsFork", "true");
tinyDB.putString("prForkFullName", ctx.getString(R.string.prDeletedFrok)); tinyDB.putString("prForkFullName", ctx.getString(R.string.prDeletedFork));
} }
} }
@ -344,7 +411,7 @@ public class DeepLinksActivity extends BaseActivity {
tinyDB.putString("repoFullName", repoOwner + "/" + repoName); tinyDB.putString("repoFullName", repoOwner + "/" + repoName);
int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId"); int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx); RepositoriesApi repositoryData = BaseApi.getInstance(ctx, RepositoriesApi.class);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName); Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
@ -415,7 +482,7 @@ public class DeepLinksActivity extends BaseActivity {
tinyDB.putString("repoBranch", repoInfo.getDefault_branch()); tinyDB.putString("repoBranch", repoInfo.getDefault_branch());
int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId"); int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx); RepositoriesApi repositoryData = BaseApi.getInstance(ctx, RepositoriesApi.class);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName); Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
@ -452,4 +519,181 @@ public class DeepLinksActivity extends BaseActivity {
} }
}); });
} }
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

@ -18,17 +18,18 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.gson.JsonElement; 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.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityEditIssueBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables; import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; 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.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
@ -44,7 +45,7 @@ import retrofit2.Callback;
public class EditIssueActivity extends BaseActivity implements View.OnClickListener { public class EditIssueActivity extends BaseActivity implements View.OnClickListener {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
private EditText editIssueTitle; private EditText editIssueTitle;
private EditText editIssueDescription; private EditText editIssueDescription;
@ -63,17 +64,15 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
private String repoName; private String repoName;
private int issueIndex; private int issueIndex;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_edit_issue;
}
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityEditIssueBinding activityEditIssueBinding = ActivityEditIssueBinding.inflate(getLayoutInflater());
setContentView(activityEditIssueBinding.getRoot());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
loginUid = tinyDB.getString("loginUid"); loginUid = tinyDB.getString("loginUid");
@ -84,17 +83,17 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
repoName = parts[1]; repoName = parts[1];
issueIndex = Integer.parseInt(tinyDB.getString("issueNumber")); issueIndex = Integer.parseInt(tinyDB.getString("issueNumber"));
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = activityEditIssueBinding.close;
editIssueButton = findViewById(R.id.editIssueButton); editIssueButton = activityEditIssueBinding.editIssueButton;
TextView toolbar_title = findViewById(R.id.toolbar_title); TextView toolbar_title = activityEditIssueBinding.toolbarTitle;
editIssueTitle = findViewById(R.id.editIssueTitle); editIssueTitle = activityEditIssueBinding.editIssueTitle;
editIssueDescription = findViewById(R.id.editIssueDescription); editIssueDescription = activityEditIssueBinding.editIssueDescription;
editIssueDueDate = findViewById(R.id.editIssueDueDate); editIssueDueDate = activityEditIssueBinding.editIssueDueDate;
// if gitea is 1.12 or higher use the new limit // if gitea is 1.12 or higher use the new limit
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;
} }
editIssueTitle.requestFocus(); editIssueTitle.requestFocus();

View File

@ -1,28 +1,28 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ListView; import android.widget.ListView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import org.gitnex.tea4j.models.FileDiffView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.adapters.FilesDiffAdapter; import org.mian.gitnex.adapters.FilesDiffAdapter;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityFileDiffBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.ParseDiff; import org.mian.gitnex.helpers.ParseDiff;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.FileDiffView;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import okhttp3.ResponseBody; import okhttp3.ResponseBody;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Response;
/** /**
* Author M M Arif * Author M M Arif
@ -35,18 +35,15 @@ public class FileDiffActivity extends BaseActivity {
private ListView mListView; private ListView mListView;
private ProgressBar mProgressBar; private ProgressBar mProgressBar;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_file_diff;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Toolbar toolbar = findViewById(R.id.toolbar); ActivityFileDiffBinding activityFileDiffBinding = ActivityFileDiffBinding.inflate(getLayoutInflater());
setContentView(activityFileDiffBinding.getRoot());
Toolbar toolbar = activityFileDiffBinding.toolbar;
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
final TinyDB tinyDb = TinyDB.getInstance(appCtx); final TinyDB tinyDb = TinyDB.getInstance(appCtx);
@ -54,13 +51,11 @@ public class FileDiffActivity extends BaseActivity {
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
final String repoOwner = parts[0]; final String repoOwner = parts[0];
final String repoName = parts[1]; 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); ImageView closeActivity = activityFileDiffBinding.close;
toolbarTitle = findViewById(R.id.toolbar_title); toolbarTitle = activityFileDiffBinding.toolbarTitle;
mListView = findViewById(R.id.listView); mListView = activityFileDiffBinding.listView;
mProgressBar = findViewById(R.id.progress_bar); mProgressBar = activityFileDiffBinding.progressBar;
mListView.setDivider(null); mListView.setDivider(null);
@ -73,79 +68,68 @@ public class FileDiffActivity extends BaseActivity {
String pullIndex = tinyDb.getString("issueNumber"); String pullIndex = tinyDb.getString("issueNumber");
boolean apiCall = !new Version(tinyDb.getString("giteaVersion")).less("1.13.0"); boolean apiCall = !new Version(tinyDb.getString("giteaVersion")).less("1.13.0");
getPullDiffContent(repoOwner, repoName, pullIndex, instanceToken, apiCall); getPullDiffContent(repoOwner, repoName, pullIndex, apiCall);
} }
private void getPullDiffContent(String owner, String repo, String pullIndex, String token, boolean apiCall) { private void getPullDiffContent(String owner, String repo, String pullIndex, boolean apiCall) {
Call<ResponseBody> call; Thread thread = new Thread(() -> {
if(apiCall) {
call = RetrofitClient.getApiInterface(ctx).getPullDiffContent(token, owner, repo, pullIndex); Call<ResponseBody> call = apiCall ?
} RetrofitClient.getApiInterface(ctx).getPullDiffContent(Authorization.get(ctx), owner, repo, pullIndex) :
else { RetrofitClient.getWebInterface(ctx).getPullDiffContent(Authorization.getWeb(ctx), owner, repo, pullIndex);
call = RetrofitClient.getWebInterface(ctx).getPullDiffContent(owner, repo, pullIndex);
}
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
if(response.code() == 200) {
try { try {
Response<ResponseBody> response = call.execute();
assert response.body() != null; assert response.body() != null;
List<FileDiffView> fileContentsArray = ParseDiff.getFileDiffViewArray(response.body().string()); switch(response.code()) {
int filesCount = fileContentsArray.size(); case 200:
if(filesCount > 1) { List<FileDiffView> fileDiffViews = ParseDiff.getFileDiffViewArray(response.body().string());
toolbarTitle.setText(getResources().getString(R.string.fileDiffViewHeader, Integer.toString(filesCount))); int filesCount = fileDiffViews.size();
}
else {
toolbarTitle.setText(getResources().getString(R.string.fileDiffViewHeaderSingle, Integer.toString(filesCount))); String toolbarTitleText = (filesCount > 1) ?
} getResources().getString(R.string.fileDiffViewHeader, Integer.toString(filesCount)) :
getResources().getString(R.string.fileDiffViewHeaderSingle, Integer.toString(filesCount));
FilesDiffAdapter adapter = new FilesDiffAdapter(ctx, getSupportFragmentManager(), fileContentsArray); FilesDiffAdapter adapter = new FilesDiffAdapter(ctx, getSupportFragmentManager(), fileDiffViews);
runOnUiThread(() -> {
toolbarTitle.setText(toolbarTitleText);
mListView.setAdapter(adapter); mListView.setAdapter(adapter);
mProgressBar.setVisibility(View.GONE); mProgressBar.setVisibility(View.GONE);
}
catch(IOException e) {
e.printStackTrace();
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.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());
}
}); });
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)));
}
} catch(IOException ignored) {}
});
thread.start();
} }
@ -155,6 +139,7 @@ public class FileDiffActivity extends BaseActivity {
getIntent().removeExtra("singleFileName"); getIntent().removeExtra("singleFileName");
finish(); finish();
}; };
} }

View File

@ -1,53 +1,41 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.app.Activity; import android.app.Activity;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.method.ScrollingMovementMethod; import android.text.method.ScrollingMovementMethod;
import android.util.Base64;
import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull; import androidx.core.app.NotificationCompat;
import androidx.appcompat.widget.Toolbar; import com.vdurmont.emoji.EmojiParser;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.util.FitPolicy;
import com.github.chrisbanes.photoview.PhotoView;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.gitnex.tea4j.models.Files;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityFileViewBinding;
import org.mian.gitnex.fragments.BottomSheetFileViewerFragment; import org.mian.gitnex.fragments.BottomSheetFileViewerFragment;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
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.Markdown;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.highlightjs.HighlightJsView; import org.mian.gitnex.notifications.Notifications;
import org.mian.gitnex.helpers.highlightjs.models.Theme;
import org.mian.gitnex.models.Files;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.util.Arrays;
import java.net.URLDecoder; import okhttp3.ResponseBody;
import java.util.Objects;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Response;
/** /**
* Author M M Arif * Author M M Arif
@ -55,79 +43,36 @@ import retrofit2.Callback;
public class FileViewActivity extends BaseActivity implements BottomSheetFileViewerFragment.BottomSheetListener { public class FileViewActivity extends BaseActivity implements BottomSheetFileViewerFragment.BottomSheetListener {
private View.OnClickListener onClickListener; private ActivityFileViewBinding binding;
private TextView singleFileContents; private Files file;
private LinearLayout singleFileContentsFrame;
private HighlightJsView singleCodeContents;
private PhotoView imageView;
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;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_file_view;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appUtil = new AppUtil();
Toolbar toolbar = findViewById(R.id.toolbar); binding = ActivityFileViewBinding.inflate(getLayoutInflater());
setSupportActionBar(toolbar);
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 repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch"); String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
final String repoOwner = parts[0]; String repoOwner = parts[0];
final String repoName = parts[1]; String repoName = parts[1];
final String loginUid = tinyDB.getString("loginUid");
final String instanceToken = "token " + tinyDB.getString(loginUid + "-token");
tinyDB.putBoolean("enableMarkdownInFileView", false); getSingleFileContents(repoOwner, repoName, file.getPath(), repoBranch);
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(instanceToken, repoOwner, repoName, singleFileName, repoBranch);
} }
@Override @Override
@ -135,157 +80,142 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
super.onResume(); super.onResume();
if(tinyDB.getBoolean("fileModified")) {
String repoFullName = tinyDB.getString("repoFullName"); String repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch"); String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
String repoOwner = parts[0]; String repoOwner = parts[0];
String repoName = parts[1]; String repoName = parts[1];
String loginUid = tinyDB.getString("loginUid");
String instanceToken = "token " + tinyDB.getString(loginUid + "-token");
if(tinyDB.getBoolean("fileModified")) { getSingleFileContents(repoOwner, repoName, file.getPath(), repoBranch);
getSingleFileContents(instanceToken, repoOwner, repoName, singleFileName, repoBranch);
tinyDB.putBoolean("fileModified", false); tinyDB.putBoolean("fileModified", false);
} }
} }
private void getSingleFileContents(final String owner, String repo, final String filename, String ref) {
private void getSingleFileContents(String token, final String owner, String repo, final String filename, String ref) { Thread thread = new Thread(() -> {
Call<Files> call = RetrofitClient.getApiInterface(ctx).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 Response<ResponseBody> response = call.execute();
public void onResponse(@NonNull Call<Files> call, @NonNull retrofit2.Response<Files> response) {
if(response.code() == 200) { 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); String fileExtension = FileUtils.getExtension(filename);
mProgressBar.setVisibility(View.GONE);
fileSha = response.body().getSha(); boolean processable = false;
// download file meta switch(AppUtil.getFileType(fileExtension)) {
tinyDB.putString("downloadFileName", filename);
tinyDB.putString("downloadFileContents", response.body().getContent());
if(appUtil.imageExtension(fileExtension)) { // file is image case IMAGE:
singleFileContentsFrame.setVisibility(View.GONE); // See https://developer.android.com/guide/topics/media/media-formats#core
singleCodeContents.setVisibility(View.GONE); if(Arrays.asList("bmp", "gif", "jpg", "jpeg", "png", "webp", "heic", "heif").contains(fileExtension.toLowerCase())) {
pdfViewFrame.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
imageData = Base64.decode(response.body().getContent(), Base64.DEFAULT); processable = true;
Drawable imageDrawable = new BitmapDrawable(getResources(), BitmapFactory.decodeByteArray(imageData, 0, imageData.length));
imageView.setImageDrawable(imageDrawable); 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));
});
} }
else if(appUtil.sourceCodeExtension(fileExtension)) { // file is sourcecode
imageView.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.VISIBLE);
switch(tinyDB.getInt("fileviewerSourceCodeThemeId")) {
case 1:
singleCodeContents.setTheme(Theme.ARDUINO_LIGHT);
break; break;
case 2:
singleCodeContents.setTheme(Theme.GITHUB); case UNKNOWN:
case TEXT:
if(file.getSize() > Constants.maximumFileViewerSize) {
break; 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())); processable = true;
} String text = responseBody.string();
else if(appUtil.pdfExtension(fileExtension)) { // file is pdf
imageView.setVisibility(View.GONE); runOnUiThread(() -> {
singleFileContentsFrame.setVisibility(View.GONE); binding.photoView.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.VISIBLE);
pdfNightMode = tinyDB.getBoolean("enablePdfMode"); binding.contents.setContent(text, fileExtension);
decodedPdf = Base64.decode(response.body().getContent(), Base64.DEFAULT); if(tinyDB.getBoolean("enableMarkdownInFileView")) {
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(); Markdown.render(ctx, EmojiParser.parseToUnicode(text), binding.markdown);
} binding.contents.setVisibility(View.GONE);
else if(appUtil.excludeFilesInFileViewerExtension(fileExtension)) { // files need to be excluded binding.markdownFrame.setVisibility(View.VISIBLE);
} else {
imageView.setVisibility(View.GONE); binding.markdownFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE); binding.contents.setVisibility(View.VISIBLE);
pdfViewFrame.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setText(getResources().getString(R.string.excludeFilesInFileviewer));
singleFileContents.setGravity(Gravity.CENTER);
singleFileContents.setTypeface(null, Typeface.BOLD);
}
else { // file type not known - plain text view
imageView.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setText(appUtil.decodeBase64(response.body().getContent()));
}
}
else {
singleFileContents.setText("");
mProgressBar.setVisibility(View.GONE);
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.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());
} }
}); });
break;
}
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();
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 {
runOnUiThread(() -> {
binding.markdown.setText("");
binding.progressBar.setVisibility(View.GONE);
});
}
} else {
switch(response.code()) {
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;
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)));
}
}
} catch(IOException ignored) {}
});
thread.start();
} }
@ -296,11 +226,11 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
inflater.inflate(R.menu.generic_nav_dotted_menu, menu); inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
inflater.inflate(R.menu.files_view_menu, menu); inflater.inflate(R.menu.files_view_menu, menu);
String fileExtension = FileUtils.getExtension(singleFileName); if(!FileUtils.getExtension(file.getName())
.equalsIgnoreCase("md")) {
if(!fileExtension.equalsIgnoreCase("md")) { menu.getItem(0)
.setVisible(false);
menu.getItem(0).setVisible(false);
} }
return true; return true;
@ -315,36 +245,32 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
finish(); finish();
return true; return true;
}
else if(id == R.id.genericMenu) { } else if(id == R.id.genericMenu) {
BottomSheetFileViewerFragment bottomSheet = new BottomSheetFileViewerFragment(); BottomSheetFileViewerFragment bottomSheet = new BottomSheetFileViewerFragment();
bottomSheet.show(getSupportFragmentManager(), "fileViewerBottomSheet"); bottomSheet.show(getSupportFragmentManager(), "fileViewerBottomSheet");
return true; return true;
}
else if(id == R.id.markdown) {
new Markdown(ctx, appUtil.decodeBase64(tinyDB.getString("downloadFileContents")), singleFileContents); } else if(id == R.id.markdown) {
if(!tinyDB.getBoolean("enableMarkdownInFileView")) { if(!tinyDB.getBoolean("enableMarkdownInFileView")) {
Markdown.render(ctx, EmojiParser.parseToUnicode(binding.contents.getContent()), binding.markdown);
binding.contents.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.VISIBLE);
singleCodeContents.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setVisibility(View.VISIBLE);
tinyDB.putBoolean("enableMarkdownInFileView", true); tinyDB.putBoolean("enableMarkdownInFileView", true);
} } else {
else { binding.markdownFrame.setVisibility(View.GONE);
binding.contents.setVisibility(View.VISIBLE);
singleCodeContents.setVisibility(View.VISIBLE);
singleFileContentsFrame.setVisibility(View.GONE);
singleFileContents.setVisibility(View.GONE);
singleCodeContents.setSource(appUtil.decodeBase64(tinyDB.getString("downloadFileContents")));
tinyDB.putBoolean("enableMarkdownInFileView", false); tinyDB.putBoolean("enableMarkdownInFileView", false);
} }
return true;
}
else {
return true;
} else {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
} }
@ -353,116 +279,120 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
public void onButtonClicked(String text) { public void onButtonClicked(String text) {
if("downloadFile".equals(text)) { if("downloadFile".equals(text)) {
requestFileDownload(); requestFileDownload();
} }
if("deleteFile".equals(text)) { if("deleteFile".equals(text)) {
String fileExtension = FileUtils.getExtension(singleFileName);
String data = appUtil.decodeBase64(tinyDB.getString("downloadFileContents"));
Intent intent = new Intent(ctx, CreateFileActivity.class); Intent intent = new Intent(ctx, CreateFileActivity.class);
intent.putExtra("fileAction", 1); intent.putExtra("fileAction", CreateFileActivity.FILE_ACTION_DELETE);
intent.putExtra("filePath", singleFileName); intent.putExtra("filePath", file.getPath());
intent.putExtra("fileSha", fileSha); intent.putExtra("fileSha", file.getSha());
if(!appUtil.imageExtension(fileExtension)) {
intent.putExtra("fileContents", data);
}
else {
intent.putExtra("fileContents", "");
}
ctx.startActivity(intent); ctx.startActivity(intent);
} }
if("editFile".equals(text)) { if("editFile".equals(text)) {
String fileExtension = FileUtils.getExtension(singleFileName); if(binding.contents.getContent() != null &&
String data = appUtil.decodeBase64(tinyDB.getString("downloadFileContents")); !binding.contents.getContent().isEmpty()) {
Intent intent = new Intent(ctx, CreateFileActivity.class); 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("fileAction", CreateFileActivity.FILE_ACTION_EDIT);
intent.putExtra("filePath", file.getPath());
intent.putExtra("fileContents", data); intent.putExtra("fileSha", file.getSha());
} intent.putExtra("fileContents", binding.contents.getContent());
else {
intent.putExtra("fileContents", "");
}
ctx.startActivity(intent); ctx.startActivity(intent);
}
} else {
Toasty.error(ctx, getString(R.string.fileTypeCannotBeEdited));
}
}
} }
private void requestFileDownload() { private void requestFileDownload() {
if(!tinyDB.getString("downloadFileContents").isEmpty()) {
File outputFileName = new File(tinyDB.getString("downloadFileName"));
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE); intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_TITLE, file.getName());
intent.setType("*/*"); intent.setType("*/*");
intent.putExtra(Intent.EXTRA_TITLE, outputFileName.getName());
fileDownloadActivityResultLauncher.launch(intent); activityResultLauncher.launch(intent);
}
else {
Toasty.warning(ctx, getString(R.string.waitLoadingDownloadFile));
}
} }
ActivityResultLauncher<Intent> fileDownloadActivityResultLauncher = registerForActivityResult( ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) { if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData(); assert result.getData() != null;
try { try {
assert data != null; OutputStream outputStream = getContentResolver().openOutputStream(result.getData().getData());
Uri uri = data.getData();
assert uri != null; NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx, ctx.getPackageName())
OutputStream outputStream = getContentResolver().openOutputStream(uri); .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; NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);;
outputStream.write(dataAsBytes); notificationManager.notify(notificationId, builder.build());
outputStream.close();
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];
} Thread thread = new Thread(() -> {
catch(IOException e) {
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());
Log.e("errorFileDownloading", Objects.requireNonNull(e.getMessage()));
}
}
} }
}); });
private void initCloseListener() { thread.start();
onClickListener = view -> { } catch(IOException ignored) {}
getIntent().removeExtra("singleFileName");
finish();
};
} }
});
} }

View File

@ -9,7 +9,6 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.text.Html;
import android.util.Log; import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -22,12 +21,19 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.ScrollView; import android.widget.ScrollView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.text.HtmlCompat;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.vdurmont.emoji.EmojiParser; 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.R;
import org.mian.gitnex.actions.AssigneesActions; import org.mian.gitnex.actions.AssigneesActions;
import org.mian.gitnex.actions.LabelsActions; import org.mian.gitnex.actions.LabelsActions;
@ -53,11 +59,6 @@ import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; 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.viewmodels.IssueCommentsViewModel;
import org.mian.gitnex.views.ReactionList; import org.mian.gitnex.views.ReactionList;
import java.text.DateFormat; import java.text.DateFormat;
@ -89,8 +90,8 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
private List<Integer> currentLabelsIds = new ArrayList<>(); private List<Integer> currentLabelsIds = new ArrayList<>();
private List<Integer> labelsIds = new ArrayList<>(); private List<Integer> labelsIds = new ArrayList<>();
private List<Labels> labelsList = new ArrayList<>(); private final List<Labels> labelsList = new ArrayList<>();
private List<Collaborators> assigneesList = new ArrayList<>(); private final List<Collaborators> assigneesList = new ArrayList<>();
private List<String> assigneesListData = new ArrayList<>(); private List<String> assigneesListData = new ArrayList<>();
private List<String> currentAssignees = new ArrayList<>(); private List<String> currentAssignees = new ArrayList<>();
@ -101,20 +102,13 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
private CustomAssigneesSelectionDialogBinding assigneesBinding; private CustomAssigneesSelectionDialogBinding assigneesBinding;
private ActivityIssueDetailBinding viewBinding; private ActivityIssueDetailBinding viewBinding;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_issue_detail;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewBinding = ActivityIssueDetailBinding.inflate(getLayoutInflater()); viewBinding = ActivityIssueDetailBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot(); setContentView(viewBinding.getRoot());
setContentView(view);
String repoFullName = tinyDB.getString("repoFullName"); String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
@ -202,6 +196,10 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
getSingleIssue(repoOwner, repoName, issueIndex); getSingleIssue(repoOwner, repoName, issueIndex);
fetchDataAsync(repoOwner, repoName, issueIndex); fetchDataAsync(repoOwner, repoName, issueIndex);
if(getIntent().getStringExtra("openPrDiff") != null && getIntent().getStringExtra("openPrDiff").equals("true")) {
startActivity(new Intent(ctx, FileDiffActivity.class));
}
} }
@Override @Override
@ -440,6 +438,11 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
if(id == android.R.id.home) { 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(); finish();
return true; return true;
} }
@ -575,7 +578,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
} }
TinyDB tinyDb = TinyDB.getInstance(appCtx); TinyDB tinyDb = TinyDB.getInstance(appCtx);
final String locale = tinyDb.getString("locale"); final Locale locale = getResources().getConfiguration().locale;
final String timeFormat = tinyDb.getString("dateFormat"); final String timeFormat = tinyDb.getString("dateFormat");
tinyDb.putString("issueState", singleIssue.getState()); tinyDb.putString("issueState", singleIssue.getState());
tinyDb.putString("issueTitle", singleIssue.getTitle()); tinyDb.putString("issueTitle", singleIssue.getTitle());
@ -583,12 +586,23 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
PicassoService.getInstance(ctx).get().load(singleIssue.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated) 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); .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>"; .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(); String cleanIssueDescription = singleIssue.getBody().trim().replace("\n", "<br/>");
new Markdown(ctx, EmojiParser.parseToUnicode(cleanIssueDescription), viewBinding.issueDescription); 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(); RelativeLayout.LayoutParams paramsDesc = (RelativeLayout.LayoutParams) viewBinding.issueDescription.getLayoutParams();
@ -609,7 +623,20 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.frameAssignees.addView(assigneesView); viewBinding.frameAssignees.addView(assigneesView);
assigneesView.setLayoutParams(params1); 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( assigneesView.setOnClickListener(
new ClickListener(getString(R.string.assignedTo, singleIssue.getAssignees().get(i).getFull_name()), ctx)); new ClickListener(getString(R.string.assignedTo, singleIssue.getAssignees().get(i).getFull_name()), ctx));
@ -618,7 +645,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
assigneesView.setOnClickListener( assigneesView.setOnClickListener(
new ClickListener(getString(R.string.assignedTo, singleIssue.getAssignees().get(i).getLogin()), ctx)); new ClickListener(getString(R.string.assignedTo, singleIssue.getAssignees().get(i).getLogin()), ctx));
} }*/
} }
} }
else { else {
@ -666,7 +693,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
if(timeFormat.equals("normal") || timeFormat.equals("pretty")) { 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()); String dueDate = formatter.format(singleIssue.getDue_date());
viewBinding.issueDueDate.setText(dueDate); viewBinding.issueDueDate.setText(dueDate);
viewBinding.issueDueDate viewBinding.issueDueDate
@ -674,7 +701,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
} }
else if(timeFormat.equals("normal1")) { 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()); String dueDate = formatter.format(singleIssue.getDue_date());
viewBinding.issueDueDate.setText(dueDate); viewBinding.issueDueDate.setText(dueDate);
} }
@ -720,7 +747,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.issueDescription.setLayoutParams(paramsDesc); 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); viewBinding.issueCreatedTime.setVisibility(View.VISIBLE);
if(timeFormat.equals("pretty")) { if(timeFormat.equals("pretty")) {
@ -756,7 +783,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.issueMilestone.setVisibility(View.GONE); viewBinding.issueMilestone.setVisibility(View.GONE);
} }
if(!singleIssue.getUser().getFull_name().equals("")) { /*if(!singleIssue.getUser().getFull_name().equals("")) {
viewBinding.assigneeAvatar.setOnClickListener( viewBinding.assigneeAvatar.setOnClickListener(
new ClickListener(ctx.getResources().getString(R.string.issueCreator) + singleIssue.getUser().getFull_name(), ctx)); new ClickListener(ctx.getResources().getString(R.string.issueCreator) + singleIssue.getUser().getFull_name(), ctx));
@ -765,7 +792,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.assigneeAvatar.setOnClickListener( viewBinding.assigneeAvatar.setOnClickListener(
new ClickListener(ctx.getResources().getString(R.string.issueCreator) + singleIssue.getUser().getLogin(), ctx)); new ClickListener(ctx.getResources().getString(R.string.issueCreator) + singleIssue.getUser().getLogin(), ctx));
} }*/
viewBinding.progressBar.setVisibility(View.GONE); viewBinding.progressBar.setVisibility(View.GONE);
} }

View File

@ -2,6 +2,7 @@ package org.mian.gitnex.activities;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
@ -9,23 +10,24 @@ import android.widget.AutoCompleteTextView;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.RadioGroup; import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; 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.R;
import org.mian.gitnex.clients.RetrofitClient; 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.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount; import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.databinding.ActivityLoginBinding;
import org.mian.gitnex.helpers.AppUtil; 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.PathsHelper;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UrlHelper; import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.helpers.Version; 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.net.URI;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
@ -52,34 +54,33 @@ public class LoginActivity extends BaseActivity {
private String device_id = "token"; private String device_id = "token";
private String selectedProtocol; private String selectedProtocol;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_login;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
NetworkObserver networkMonitor = new NetworkObserver(ctx); ActivityLoginBinding activityLoginBinding = ActivityLoginBinding.inflate(getLayoutInflater());
setContentView(activityLoginBinding.getRoot());
loginButton = findViewById(R.id.login_button); NetworkStatusObserver networkStatusObserver = NetworkStatusObserver.getInstance(ctx);
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);
((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()); 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) -> { protocolSpinner.setOnItemClickListener((parent, view, position, id) -> {
selectedProtocol = String.valueOf(parent.getItemAtPosition(position)); selectedProtocol = String.valueOf(parent.getItemAtPosition(position));
@ -115,9 +116,13 @@ public class LoginActivity extends BaseActivity {
} }
}); });
networkMonitor.onInternetStateListener(isAvailable -> { Handler handler = new Handler(getMainLooper());
if(isAvailable) { networkStatusObserver.registerNetworkStatusListener(hasNetworkConnection -> {
handler.post(() -> {
if(hasNetworkConnection) {
enableProcessButton(); enableProcessButton();
} }
@ -127,6 +132,8 @@ public class LoginActivity extends BaseActivity {
loginButton.setText(getResources().getString(R.string.btnLogin)); loginButton.setText(getResources().getString(R.string.btnLogin));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
} }
});
}); });
loadDefaults(); loadDefaults();
@ -267,11 +274,13 @@ public class LoginActivity extends BaseActivity {
if(gitea_version.less(getString(R.string.versionLow))) { if(gitea_version.less(getString(R.string.versionLow))) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(ctx).setTitle(getString(R.string.versionAlertDialogHeader)) AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(ctx)
.setMessage(getResources().getString(R.string.versionUnsupportedOld, version.getVersion())).setIcon(R.drawable.ic_warning) .setTitle(getString(R.string.versionAlertDialogHeader))
.setMessage(getResources().getString(R.string.versionUnsupportedOld, version.getVersion()))
.setIcon(R.drawable.ic_warning)
.setCancelable(true); .setCancelable(true);
alertDialogBuilder.setNegativeButton(getString(R.string.cancelButton), (dialog, which) -> { alertDialogBuilder.setNeutralButton(getString(R.string.cancelButton), (dialog, which) -> {
dialog.dismiss(); dialog.dismiss();
enableProcessButton(); enableProcessButton();
@ -352,19 +361,19 @@ public class LoginActivity extends BaseActivity {
// insert new account to db if does not exist // insert new account to db if does not exist
String accountName = userDetails.getUsername() + "@" + TinyDB.getInstance(ctx).getString("instanceUrl"); String accountName = userDetails.getUsername() + "@" + TinyDB.getInstance(ctx).getString("instanceUrl");
UserAccountsApi userAccountsApi = new UserAccountsApi(ctx); UserAccountsApi userAccountsApi = BaseApi.getInstance(ctx, UserAccountsApi.class);
int checkAccount = userAccountsApi.getCount(accountName); boolean userAccountExists = userAccountsApi.userAccountExists(accountName);
long accountId; long accountId;
if(checkAccount == 0) { if(!userAccountExists) {
accountId = userAccountsApi.insertNewAccount(accountName, TinyDB.getInstance(ctx).getString("instanceUrl"), userDetails.getUsername(), loginToken, ""); accountId = userAccountsApi.createNewAccount(accountName, TinyDB.getInstance(ctx).getString("instanceUrl"), userDetails.getUsername(), loginToken, "");
tinyDB.putInt("currentActiveAccountId", (int) accountId); tinyDB.putInt("currentActiveAccountId", (int) accountId);
} }
else { else {
userAccountsApi.updateTokenByAccountName(accountName, loginToken); userAccountsApi.updateTokenByAccountName(accountName, loginToken);
UserAccount data = userAccountsApi.getAccountData(accountName); UserAccount data = userAccountsApi.getAccountByName(accountName);
tinyDB.putInt("currentActiveAccountId", data.getAccountId()); tinyDB.putInt("currentActiveAccountId", data.getAccountId());
} }
@ -540,20 +549,20 @@ public class LoginActivity extends BaseActivity {
// insert new account to db if does not exist // insert new account to db if does not exist
String accountName = userDetails.getUsername() + "@" + TinyDB.getInstance(ctx).getString("instanceUrl"); String accountName = userDetails.getUsername() + "@" + TinyDB.getInstance(ctx).getString("instanceUrl");
UserAccountsApi userAccountsApi = new UserAccountsApi(ctx); UserAccountsApi userAccountsApi = BaseApi.getInstance(ctx, UserAccountsApi.class);
int checkAccount = userAccountsApi.getCount(accountName); boolean userAccountExists = userAccountsApi.userAccountExists(accountName);
long accountId; long accountId;
if(checkAccount == 0) { if(!userAccountExists) {
accountId = userAccountsApi accountId = userAccountsApi
.insertNewAccount(accountName, TinyDB.getInstance(ctx).getString("instanceUrl"), userDetails.getUsername(), newToken.getSha1(), ""); .createNewAccount(accountName, TinyDB.getInstance(ctx).getString("instanceUrl"), userDetails.getUsername(), newToken.getSha1(), "");
tinyDB.putInt("currentActiveAccountId", (int) accountId); tinyDB.putInt("currentActiveAccountId", (int) accountId);
} }
else { else {
userAccountsApi.updateTokenByAccountName(accountName, newToken.getSha1()); userAccountsApi.updateTokenByAccountName(accountName, newToken.getSha1());
UserAccount data = userAccountsApi.getAccountData(accountName); UserAccount data = userAccountsApi.getAccountByName(accountName);
tinyDB.putInt("currentActiveAccountId", data.getAccountId()); tinyDB.putInt("currentActiveAccountId", data.getAccountId());
} }

View File

@ -3,15 +3,13 @@ package org.mian.gitnex.activities;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -19,18 +17,24 @@ import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.cardview.widget.CardView;
import androidx.core.view.GravityCompat; import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.navigation.NavigationView; 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.R;
import org.mian.gitnex.adapters.UserAccountsNavAdapter; import org.mian.gitnex.adapters.UserAccountsNavAdapter;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient; 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.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount; import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.databinding.ActivityMainBinding;
import org.mian.gitnex.fragments.AdministrationFragment; import org.mian.gitnex.fragments.AdministrationFragment;
import org.mian.gitnex.fragments.BottomSheetDraftsFragment; import org.mian.gitnex.fragments.BottomSheetDraftsFragment;
import org.mian.gitnex.fragments.DraftsFragment; 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.MyRepositoriesFragment;
import org.mian.gitnex.fragments.NotificationsFragment; import org.mian.gitnex.fragments.NotificationsFragment;
import org.mian.gitnex.fragments.OrganizationsFragment; 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.RepositoriesFragment;
import org.mian.gitnex.fragments.SettingsFragment; import org.mian.gitnex.fragments.SettingsFragment;
import org.mian.gitnex.fragments.StarredRepositoriesFragment; 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.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; 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.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import jp.wasabeef.picasso.transformations.BlurTransformation;
import eightbitlab.com.blurview.BlurView;
import eightbitlab.com.blurview.RenderScriptBlur;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -70,12 +69,6 @@ import retrofit2.Callback;
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener, BottomSheetDraftsFragment.BottomSheetListener { public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener, BottomSheetDraftsFragment.BottomSheetListener {
private DrawerLayout drawer; private DrawerLayout drawer;
private BlurView blurView;
private TextView userFullName;
private TextView userEmail;
private ImageView userAvatar;
private ImageView userAvatarBackground;
private ViewGroup navHeaderFrame;
private TextView toolbarTitle; private TextView toolbarTitle;
private Typeface myTypeface; private Typeface myTypeface;
@ -86,49 +79,33 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
private MenuItem navNotifications; private MenuItem navNotifications;
private TextView notificationCounter; private TextView notificationCounter;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_main;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
tinyDB.putBoolean("noConnection", false); ActivityMainBinding activityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(activityMainBinding.getRoot());
String currentVersion = tinyDB.getString("giteaVersion");
Intent mainIntent = getIntent(); Intent mainIntent = getIntent();
String launchFragment = mainIntent.getStringExtra("launchFragment");
// 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;
}
// DO NOT MOVE
tinyDB.putBoolean("noConnection", false);
loginUid = tinyDB.getString("loginUid"); loginUid = tinyDB.getString("loginUid");
instanceToken = "token " + tinyDB.getString(loginUid + "-token"); instanceToken = "token " + tinyDB.getString(loginUid + "-token");
if(tinyDB.getString("dateFormat").isEmpty()) {
tinyDB.putString("dateFormat", "pretty");
}
if(tinyDB.getString("codeBlockStr").isEmpty()) {
tinyDB.putInt("codeBlockColor", getResources().getColor(R.color.colorLightGreen));
tinyDB.putInt("codeBlockBackground", getResources().getColor(R.color.black));
}
if(tinyDB.getString("enableCounterIssueBadgeInit").isEmpty()) {
tinyDB.putBoolean("enableCounterIssueBadge", true);
}
if(tinyDB.getString("homeScreenStr").isEmpty()) {
tinyDB.putString("homeScreenStr", "yes");
tinyDB.putInt("homeScreenId", 0);
}
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
if(!tinyDB.getBoolean("loggedInMode")) { if(!tinyDB.getBoolean("loggedInMode")) {
@ -137,28 +114,29 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
return; return;
} }
if(tinyDB.getInt("currentActiveAccountId") <= 0) { if(tinyDB.getInt("currentActiveAccountId", -1) <= 0) {
AlertDialogs.forceLogoutDialog(ctx,
AlertDialogs.forceLogoutDialog(ctx, getResources().getString(R.string.forceLogoutDialogHeader), getResources().getString(R.string.forceLogoutDialogDescription), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); getResources().getString(R.string.forceLogoutDialogHeader),
getResources().getString(R.string.forceLogoutDialogDescription), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
} }
Toolbar toolbar = findViewById(R.id.toolbar); Toolbar toolbar = activityMainBinding.toolbar;
toolbarTitle = toolbar.findViewById(R.id.toolbar_title); toolbarTitle = activityMainBinding.toolbarTitle;
switch(tinyDB.getInt("customFontId", -1)) { switch(tinyDB.getInt("customFontId", -1)) {
case 0: case 0:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/roboto.ttf"); myTypeface = Typeface.createFromAsset(getAssets(), "fonts/roboto.ttf");
break; break;
case 2:
case 2:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/sourcecodeproregular.ttf"); myTypeface = Typeface.createFromAsset(getAssets(), "fonts/sourcecodeproregular.ttf");
break; break;
default:
default:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/manroperegular.ttf"); myTypeface = Typeface.createFromAsset(getAssets(), "fonts/manroperegular.ttf");
break; break;
} }
toolbarTitle.setTypeface(myTypeface); toolbarTitle.setTypeface(myTypeface);
@ -168,57 +146,47 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
Fragment fragmentById = fm.findFragmentById(R.id.fragment_container); Fragment fragmentById = fm.findFragmentById(R.id.fragment_container);
if(fragmentById instanceof SettingsFragment) { if(fragmentById instanceof SettingsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings)); toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
} }
else if(fragmentById instanceof MyRepositoriesFragment) { else if(fragmentById instanceof MyRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos)); toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
} }
else if(fragmentById instanceof StarredRepositoriesFragment) { else if(fragmentById instanceof StarredRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos)); toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
} }
else if(fragmentById instanceof OrganizationsFragment) { else if(fragmentById instanceof OrganizationsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations)); toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
} }
else if(fragmentById instanceof ExploreFragment) { else if(fragmentById instanceof ExploreFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore)); toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
} }
else if(fragmentById instanceof NotificationsFragment) { else if(fragmentById instanceof NotificationsFragment) {
toolbarTitle.setText(R.string.pageTitleNotifications); toolbarTitle.setText(R.string.pageTitleNotifications);
} }
else if(fragmentById instanceof ProfileFragment) { else if(fragmentById instanceof MyProfileFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile)); toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
} }
else if(fragmentById instanceof DraftsFragment) { else if(fragmentById instanceof DraftsFragment) {
toolbarTitle.setText(getResources().getString(R.string.titleDrafts)); toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
} }
else if(fragmentById instanceof AdministrationFragment) { else if(fragmentById instanceof AdministrationFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration)); toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
} }
else if(fragmentById instanceof UserAccountsFragment) { else if(fragmentById instanceof UserAccountsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleUserAccounts)); toolbarTitle.setText(getResources().getString(R.string.pageTitleUserAccounts));
} }
getNotificationsCount(instanceToken); getNotificationsCount(instanceToken);
drawer = findViewById(R.id.drawer_layout); drawer = activityMainBinding.drawerLayout;
NavigationView navigationView = findViewById(R.id.nav_view); NavigationView navigationView = activityMainBinding.navView;
navigationView.setNavigationItemSelectedListener(this); navigationView.setNavigationItemSelectedListener(this);
hView = navigationView.getHeaderView(0); hView = navigationView.getHeaderView(0);
Menu menu = navigationView.getMenu(); Menu menu = navigationView.getMenu();
navNotifications = menu.findItem(R.id.nav_notifications); 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(toggle);
drawer.addDrawerListener(new DrawerLayout.DrawerListener() { drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
@ -236,29 +204,26 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
String userFullNameNav = tinyDB.getString("userFullname"); String userFullNameNav = tinyDB.getString("userFullname");
String userAvatarNav = tinyDB.getString("userAvatar"); String userAvatarNav = tinyDB.getString("userAvatar");
blurView = hView.findViewById(R.id.blurView); TextView userEmail = hView.findViewById(R.id.userEmail);
userEmail = hView.findViewById(R.id.userEmail); TextView userFullName = hView.findViewById(R.id.userFullname);
userFullName = hView.findViewById(R.id.userFullname); ImageView userAvatar = hView.findViewById(R.id.userAvatar);
userAvatar = hView.findViewById(R.id.userAvatar); ImageView userAvatarBackground = hView.findViewById(R.id.userAvatarBackground);
userAvatarBackground = hView.findViewById(R.id.userAvatarBackground); CardView navRecyclerViewFrame = hView.findViewById(R.id.userAccountsFrame);
navHeaderFrame = hView.findViewById(R.id.navHeaderFrame);
List<UserAccount> userAccountsList; List<UserAccount> userAccountsList = new ArrayList<>();
userAccountsList = new ArrayList<>();
UserAccountsApi userAccountsApi; 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; UserAccountsNavAdapter adapterUserAccounts;
adapterUserAccounts = new UserAccountsNavAdapter(ctx, userAccountsList, drawer, toolbarTitle); adapterUserAccounts = new UserAccountsNavAdapter(ctx, userAccountsList, drawer, toolbarTitle);
userAccountsApi.getAllAccounts().observe((AppCompatActivity) ctx, userAccounts -> { userAccountsApi.getAllAccounts().observe((AppCompatActivity) ctx, userAccounts -> {
if(userAccounts.size() > 0) { if(userAccounts.size() > 0) {
userAccountsList.addAll(userAccounts); userAccountsList.addAll(userAccounts);
navRecyclerViewUserAccounts.setAdapter(adapterUserAccounts); navRecyclerViewUserAccounts.setAdapter(adapterUserAccounts);
navRecyclerViewFrame.setVisibility(View.VISIBLE);
} }
}); });
@ -266,53 +231,48 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
userFullName.setTypeface(myTypeface); userFullName.setTypeface(myTypeface);
if(!userEmailNav.equals("")) { if(!userEmailNav.equals("")) {
userEmail.setText(userEmailNav); userEmail.setText(userEmailNav);
} }
if(!userFullNameNav.equals("")) { if(!userFullNameNav.equals("")) {
userFullName.setText(Html.fromHtml(userFullNameNav));
userFullName.setText(userFullNameNav);
} }
if(!userAvatarNav.equals("")) { if(!userAvatarNav.equals("")) {
int avatarRadius = AppUtil.getPixelsFromDensity(ctx, 3);
PicassoService.getInstance(ctx).get() PicassoService.getInstance(ctx).get()
.load(userAvatarNav) .load(userAvatarNav)
.placeholder(R.drawable.loader_animated) .placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(8, 0)) .transform(new RoundedTransformation(avatarRadius, 0))
.resize(160, 160) .resize(160, 160)
.centerCrop().into(userAvatar); .centerCrop().into(userAvatar);
PicassoService.getInstance(ctx).get() PicassoService.getInstance(ctx).get()
.load(userAvatarNav) .load(userAvatarNav)
.transform(new BlurTransformation(ctx))
.into(userAvatarBackground, new com.squareup.picasso.Callback() { .into(userAvatarBackground, new com.squareup.picasso.Callback() {
@Override @Override
public void onSuccess() { public void onSuccess() {
int textColor = new ColorInverter().getImageViewContrastColor(userAvatarBackground); int textColor = new ColorInverter().getImageViewContrastColor(userAvatarBackground);
userFullName.setTextColor(textColor); userFullName.setTextColor(textColor);
userEmail.setTextColor(textColor); userEmail.setTextColor(textColor);
blurView.setupWith(navHeaderFrame)
.setBlurAlgorithm(new RenderScriptBlur(ctx))
.setBlurRadius(5)
.setHasFixedTransformationMatrix(false);
} }
@Override @Override public void onError(Exception e) {}
public void onError(Exception e) {}
}); });
} }
userAvatar.setOnClickListener(v -> { userAvatar.setOnClickListener(v -> {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile)); 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); navigationView.setCheckedItem(R.id.nav_profile);
drawer.closeDrawers(); drawer.closeDrawers();
}); });
getNotificationsCount(instanceToken); getNotificationsCount(instanceToken);
@ -322,7 +282,8 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) { 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_administration).setVisible(tinyDB.getBoolean("userIsAdmin"));
navigationView.getMenu().findItem(R.id.nav_notifications).setVisible(new Version(currentVersion).higherOrEqual("1.12.3")); navigationView.getMenu().findItem(R.id.nav_notifications).setVisible(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.3"));
} }
@Override @Override
@ -336,6 +297,8 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
toggle.syncState(); toggle.syncState();
toolbar.setNavigationIcon(R.drawable.ic_menu); toolbar.setNavigationIcon(R.drawable.ic_menu);
String launchFragment = mainIntent.getStringExtra("launchFragment");
if(launchFragment != null) { if(launchFragment != null) {
mainIntent.removeExtra("launchFragment"); mainIntent.removeExtra("launchFragment");
@ -343,13 +306,12 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
switch(launchFragment) { switch(launchFragment) {
case "drafts": case "drafts":
toolbarTitle.setText(getResources().getString(R.string.titleDrafts)); toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_comments_draft); navigationView.setCheckedItem(R.id.nav_comments_draft);
return; return;
case "notifications":
case "notifications":
toolbarTitle.setText(getResources().getString(R.string.pageTitleNotifications)); toolbarTitle.setText(getResources().getString(R.string.pageTitleNotifications));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications); navigationView.setCheckedItem(R.id.nav_notifications);
@ -366,34 +328,43 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
switch(launchFragmentByHandler) { switch(launchFragmentByHandler) {
case "repos": case "repos":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories); navigationView.setCheckedItem(R.id.nav_repositories);
return; return;
case "org":
case "org":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations); navigationView.setCheckedItem(R.id.nav_organizations);
return; return;
case "notification":
case "notification":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications); navigationView.setCheckedItem(R.id.nav_notifications);
setActionBarTitle(getResources().getString(R.string.pageTitleNotifications));
return; return;
case "explore":
case "explore":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
navigationView.setCheckedItem(R.id.nav_explore); navigationView.setCheckedItem(R.id.nav_explore);
return; 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(savedInstanceState == null) {
if(!new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.3")) { if(!new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.3")) {
if(tinyDB.getInt("homeScreenId") == 7) { if(tinyDB.getInt("homeScreenId") == 7) {
tinyDB.putInt("homeScreenId", 0); tinyDB.putInt("homeScreenId", 0);
} }
} }
@ -401,49 +372,48 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
switch(tinyDB.getInt("homeScreenId")) { switch(tinyDB.getInt("homeScreenId")) {
case 1: case 1:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos)); toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_starred_repos); navigationView.setCheckedItem(R.id.nav_starred_repos);
break; break;
case 2:
case 2:
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations)); toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations); navigationView.setCheckedItem(R.id.nav_organizations);
break; break;
case 3:
case 3:
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories)); toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories); navigationView.setCheckedItem(R.id.nav_repositories);
break; break;
case 4:
case 4:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile)); 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); navigationView.setCheckedItem(R.id.nav_profile);
break; break;
case 5:
case 5:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore)); toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
navigationView.setCheckedItem(R.id.nav_explore); navigationView.setCheckedItem(R.id.nav_explore);
break; break;
case 6:
case 6:
toolbarTitle.setText(getResources().getString(R.string.titleDrafts)); toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_comments_draft); navigationView.setCheckedItem(R.id.nav_comments_draft);
break; break;
case 7:
case 7:
toolbarTitle.setText(getResources().getString(R.string.pageTitleNotifications)); toolbarTitle.setText(getResources().getString(R.string.pageTitleNotifications));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications); navigationView.setCheckedItem(R.id.nav_notifications);
break; break;
default:
default:
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos)); toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home); navigationView.setCheckedItem(R.id.nav_home);
@ -468,17 +438,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
} }
// Changelog popup // Changelog popup
int versionCode = 0; int versionCode = AppUtil.getAppBuildNo(appCtx);
try {
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")) { if(versionCode > tinyDB.getInt("versionCode")) {
@ -569,7 +529,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
else if(id == R.id.nav_profile) { else if(id == R.id.nav_profile) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile)); 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();
} }
else if(id == R.id.nav_repositories) { else if(id == R.id.nav_repositories) {
@ -645,29 +605,22 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
private void giteaVersion() { private void giteaVersion() {
final TinyDB tinyDb = TinyDB.getInstance(appCtx); Call<GiteaVersion> callVersion = RetrofitClient.getApiInterface(ctx).getGiteaVersionWithToken(Authorization.get(ctx));
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
Call<GiteaVersion> callVersion = RetrofitClient.getApiInterface(ctx).getGiteaVersionWithToken(token);
callVersion.enqueue(new Callback<GiteaVersion>() { callVersion.enqueue(new Callback<GiteaVersion>() {
@Override @Override
public void onResponse(@NonNull final Call<GiteaVersion> callVersion, @NonNull retrofit2.Response<GiteaVersion> responseVersion) { public void onResponse(@NonNull final Call<GiteaVersion> callVersion, @NonNull retrofit2.Response<GiteaVersion> responseVersion) {
if(responseVersion.code() == 200) { if(responseVersion.code() == 200 && responseVersion.body() != null) {
String version = responseVersion.body().getVersion();
GiteaVersion version = responseVersion.body(); tinyDB.putString("giteaVersion", version);
assert version != null; BaseApi.getInstance(ctx, UserAccountsApi.class).updateServerVersion(version, tinyDB.getInt("currentActiveAccountId"));
tinyDb.putString("giteaVersion", version.getVersion());
} }
} }
@Override @Override
public void onFailure(@NonNull Call<GiteaVersion> callVersion, @NonNull Throwable t) { public void onFailure(@NonNull Call<GiteaVersion> callVersion, @NonNull Throwable t) {
Log.e("onFailure-version", t.toString()); Log.e("onFailure-version", t.toString());
} }
}); });

View File

@ -9,7 +9,10 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.gson.JsonElement; 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.R;
import org.mian.gitnex.actions.PullRequestActions;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityMergePullRequestBinding; import org.mian.gitnex.databinding.ActivityMergePullRequestBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
@ -17,11 +20,8 @@ import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; 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.ArrayList;
import java.util.Objects; import java.util.Objects;
import okhttp3.ResponseBody;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -41,12 +41,6 @@ public class MergePullRequestActivity extends BaseActivity {
private String Do; private String Do;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_merge_pull_request;
}
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -54,8 +48,7 @@ public class MergePullRequestActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewBinding = ActivityMergePullRequestBinding.inflate(getLayoutInflater()); viewBinding = ActivityMergePullRequestBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot(); setContentView(viewBinding.getRoot());
setContentView(view);
String repoFullName = tinyDB.getString("repoFullName"); String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
@ -177,12 +170,12 @@ public class MergePullRequestActivity extends BaseActivity {
MergePullRequest mergePR = new MergePullRequest(Do, mergePRDT, mergeTitle); MergePullRequest mergePR = new MergePullRequest(Do, mergePRDT, mergeTitle);
Call<ResponseBody> call = RetrofitClient.getApiInterface(ctx).mergePullRequest(Authorization.get(ctx), 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 @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(response.code() == 200) {
@ -195,7 +188,7 @@ public class MergePullRequestActivity extends BaseActivity {
final String repoOwner = parts[0]; final String repoOwner = parts[0];
final String repoName = parts[1]; final String repoName = parts[1];
deleteBranchFunction(repoOwner, repoName); PullRequestActions.deleteHeadBranch(ctx, repoOwner, repoName, tinyDB.getString("prHeadBranch"), false);
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg)); Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
tinyDB.putBoolean("prMerged", true); tinyDB.putBoolean("prMerged", true);
@ -209,7 +202,7 @@ public class MergePullRequestActivity extends BaseActivity {
final String repoOwner = parts[0]; final String repoOwner = parts[0];
final String repoName = parts[1]; final String repoName = parts[1];
deleteBranchFunction(repoOwner, repoName); PullRequestActions.deleteHeadBranch(ctx, repoOwner, repoName, tinyDB.getString("prHeadBranch"), false);
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg)); Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
tinyDB.putBoolean("prMerged", true); tinyDB.putBoolean("prMerged", true);
@ -251,37 +244,7 @@ public class MergePullRequestActivity extends BaseActivity {
} }
@Override @Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<Void> 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
.getApiInterface(ctx)
.deleteBranch(Authorization.get(ctx), 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) {
Log.e("onFailure", t.toString()); Log.e("onFailure", t.toString());
enableProcessButton(); enableProcessButton();

View File

@ -11,14 +11,15 @@ import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import org.gitnex.tea4j.models.AddEmail;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityProfileEmailBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.AddEmail;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -29,29 +30,27 @@ import retrofit2.Callback;
* Author M M Arif * Author M M Arif
*/ */
public class ProfileEmailActivity extends BaseActivity { public class MyProfileEmailActivity extends BaseActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private EditText userEmail; private EditText userEmail;
private Button addEmailButton; private Button addEmailButton;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_profile_email;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityProfileEmailBinding activityProfileEmailBinding = ActivityProfileEmailBinding.inflate(getLayoutInflater());
setContentView(activityProfileEmailBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = activityProfileEmailBinding.close;
userEmail = findViewById(R.id.userEmail); userEmail = activityProfileEmailBinding.userEmail;
addEmailButton = findViewById(R.id.addEmailButton); addEmailButton = activityProfileEmailBinding.addEmailButton;
userEmail.requestFocus(); userEmail.requestFocus();
assert imm != null; assert imm != null;

View File

@ -36,20 +36,17 @@ import io.mikael.urlbuilder.UrlBuilder;
public class OrganizationDetailActivity extends BaseActivity implements BottomSheetOrganizationFragment.BottomSheetListener { public class OrganizationDetailActivity extends BaseActivity implements BottomSheetOrganizationFragment.BottomSheetListener {
@Override
protected int getLayoutResourceId(){
return R.layout.activity_org_detail;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_org_detail);
String orgName = tinyDB.getString("orgName"); String orgName = tinyDB.getString("orgName");
Toolbar toolbar = findViewById(R.id.toolbar); Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title); TextView toolbarTitle = findViewById(R.id.toolbar_title);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(orgName); Objects.requireNonNull(getSupportActionBar()).setTitle(orgName);
@ -215,7 +212,7 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
@Override @Override
public int getCount() { public int getCount() {
return 4; return 5;
} }
} }
} }

View File

@ -14,6 +14,7 @@ import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.adapters.TeamMembersByOrgAdapter; import org.mian.gitnex.adapters.TeamMembersByOrgAdapter;
import org.mian.gitnex.databinding.ActivityOrgTeamMembersBinding;
import org.mian.gitnex.fragments.BottomSheetOrganizationTeamsFragment; import org.mian.gitnex.fragments.BottomSheetOrganizationTeamsFragment;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
@ -34,24 +35,22 @@ public class OrganizationTeamMembersActivity extends BaseActivity implements Bot
private String teamId; private String teamId;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_org_team_members;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Toolbar toolbar = findViewById(R.id.toolbar); ActivityOrgTeamMembersBinding activityOrgTeamMembersBinding = ActivityOrgTeamMembersBinding.inflate(getLayoutInflater());
setContentView(activityOrgTeamMembersBinding.getRoot());
Toolbar toolbar = activityOrgTeamMembersBinding.toolbar;
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = activityOrgTeamMembersBinding.close;
TextView toolbarTitle = findViewById(R.id.toolbar_title); TextView toolbarTitle = activityOrgTeamMembersBinding.toolbarTitle;
noDataMembers = findViewById(R.id.noDataMembers); noDataMembers = activityOrgTeamMembersBinding.noDataMembers;
mGridView = findViewById(R.id.gridView); mGridView = activityOrgTeamMembersBinding.gridView;
progressBar = findViewById(R.id.progressBar); progressBar = activityOrgTeamMembersBinding.progressBar;
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);

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,10 +1,10 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.graphics.Typeface; import android.graphics.Typeface;
@ -17,6 +17,7 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
@ -27,6 +28,10 @@ import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager; import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayout;
import com.google.gson.JsonElement; 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.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BottomSheetIssuesFilterFragment; import org.mian.gitnex.fragments.BottomSheetIssuesFilterFragment;
@ -44,9 +49,6 @@ import org.mian.gitnex.fragments.RepoInfoFragment;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; 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.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -69,9 +71,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
private FragmentRefreshListenerPr fragmentRefreshListenerPr; private FragmentRefreshListenerPr fragmentRefreshListenerPr;
private FragmentRefreshListenerMilestone fragmentRefreshListenerMilestone; private FragmentRefreshListenerMilestone fragmentRefreshListenerMilestone;
private FragmentRefreshListenerFiles fragmentRefreshListenerFiles; private FragmentRefreshListenerFiles fragmentRefreshListenerFiles;
private FragmentRefreshListenerFilterIssuesByMilestone fragmentRefreshListenerFilterIssuesByMilestone;
private String loginUid;
private String instanceToken;
private String repositoryOwner; private String repositoryOwner;
private String repositoryName; private String repositoryName;
@ -79,33 +79,34 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
public static ViewPager mViewPager; public static ViewPager mViewPager;
private int tabsCount; private int tabsCount;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_repo_detail;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_repo_detail);
String[] repoNameParts = tinyDB.getString("repoFullName").split("/"); String[] repoNameParts = tinyDB.getString("repoFullName").split("/");
repositoryOwner = repoNameParts[0]; repositoryOwner = repoNameParts[0];
repositoryName = repoNameParts[1]; repositoryName = repoNameParts[1];
Toolbar toolbar = findViewById(R.id.toolbar); 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); toolbarTitle.setText(repositoryName);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repositoryName); Objects.requireNonNull(getSupportActionBar()).setTitle(repositoryName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
loginUid = tinyDB.getString("loginUid");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
tinyDB.putString("repoIssuesState", "open"); tinyDB.putString("repoIssuesState", "open");
tinyDB.putString("repoPrState", "open"); tinyDB.putString("repoPrState", "open");
tinyDB.putString("milestoneState", "open"); tinyDB.putString("milestoneState", "open");
@ -233,13 +234,84 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
mainIntent.removeExtra("goToSection"); mainIntent.removeExtra("goToSection");
mainIntent.removeExtra("goToSectionType"); mainIntent.removeExtra("goToSectionType");
if(goToSectionType.equals("issue")) { switch(goToSectionType) {
case "branchesList":
RepoDetailActivity.mViewPager.setCurrentItem(2); 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);
} }
else if(goToSectionType.equals("pull")) { 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); 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;
} }
} }
@ -271,47 +343,50 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
int id = item.getItemId(); int id = item.getItemId();
switch(id) { if(id == android.R.id.home) {
case android.R.id.home:
finish(); finish();
return true; return true;
}
else if(id == R.id.repoMenu) {
case R.id.repoMenu:
BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment(); BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment();
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet"); bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
return true; return true;
}
else if(id == R.id.filter) {
case R.id.filter:
BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment(); BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment();
filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet"); filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet");
return true; return true;
}
else if(id == R.id.filterPr) {
case R.id.filterPr:
BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment(); BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment();
filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet"); filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet");
return true; return true;
}
else if(id == R.id.filterMilestone) {
case R.id.filterMilestone:
BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment(); BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment();
filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet"); filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet");
return true; return true;
}
else if(id == R.id.switchBranches) {
case R.id.switchBranches:
chooseBranch(); chooseBranch();
return true; return true;
}
else if(id == R.id.branchCommits) {
case R.id.branchCommits:
Intent intent = new Intent(ctx, CommitsActivity.class); Intent intent = new Intent(ctx, CommitsActivity.class);
intent.putExtra("branchName", tinyDB.getString("repoBranch")); intent.putExtra("branchName", tinyDB.getString("repoBranch"));
ctx.startActivity(intent); ctx.startActivity(intent);
return true; return true;
default:
return super.onOptionsItemSelected(item);
} }
return super.onOptionsItemSelected(item);
} }
@Override @Override
@ -368,6 +443,9 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
startActivity(new Intent(RepoDetailActivity.this, CreateFileActivity.class)); startActivity(new Intent(RepoDetailActivity.this, CreateFileActivity.class));
break; break;
case "filterByMilestone":
filterIssuesByMilestone();
break;
case "openIssues": case "openIssues":
if(getFragmentRefreshListener() != null) { if(getFragmentRefreshListener() != null) {
@ -421,17 +499,83 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
} }
} }
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() { private void chooseBranch() {
Dialog progressDialog = new Dialog(this);
progressDialog.setContentView(R.layout.custom_progress_loader);
progressDialog.show();
Call<List<Branches>> call = RetrofitClient Call<List<Branches>> call = RetrofitClient
.getApiInterface(ctx) .getApiInterface(ctx)
.getBranches(instanceToken, repositoryOwner, repositoryName); .getBranches(Authorization.get(ctx), repositoryOwner, repositoryName);
call.enqueue(new Callback<List<Branches>>() { call.enqueue(new Callback<List<Branches>>() {
@Override @Override
public void onResponse(@NonNull Call<List<Branches>> call, @NonNull Response<List<Branches>> response) { public void onResponse(@NonNull Call<List<Branches>> call, @NonNull Response<List<Branches>> response) {
progressDialog.hide();
if(response.code() == 200) { if(response.code() == 200) {
List<String> branchesList = new ArrayList<>(); List<String> branchesList = new ArrayList<>();
@ -444,7 +588,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
branchesList.add(branches.getName()); branchesList.add(branches.getName());
if(tinyDB.getString("repoBranch").equals(branches.getName())) { if(tinyDB.getString("repoBranch").equals(branches.getName())) {
selectedBranch = i; selectedBranch = i;
} }
} }
@ -452,33 +595,27 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx); AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx);
pBuilder.setTitle(R.string.pageTitleChooseBranch); 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) { if(getFragmentRefreshListenerFiles() != null) {
getFragmentRefreshListenerFiles().onRefresh(branchesList.get(i)); getFragmentRefreshListenerFiles().onRefresh(branchesList.get(i));
} }
dialogInterface.dismiss(); dialogInterface.dismiss();
}
}); });
pBuilder.setNeutralButton(R.string.cancelButton, null);
pBuilder.setNeutralButton(R.string.cancelButton, null);
pBuilder.create().show(); pBuilder.create().show();
} }
} }
@Override @Override
public void onFailure(@NonNull Call<List<Branches>> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<List<Branches>> call, @NonNull Throwable t) {
progressDialog.hide();
Log.e("onFailure", t.toString()); Log.e("onFailure", t.toString());
} }
}); });
} }
public class SectionsPagerAdapter extends FragmentStatePagerAdapter { public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
@ -642,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 // Issues interface
public FragmentRefreshListener getFragmentRefreshListener() { return fragmentRefreshListener; } public FragmentRefreshListener getFragmentRefreshListener() { return fragmentRefreshListener; }

View File

@ -21,14 +21,15 @@ import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.gitnex.tea4j.models.UserRepositories;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoForksAdapter; import org.mian.gitnex.adapters.RepoForksAdapter;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityRepoForksBinding;
import org.mian.gitnex.helpers.Authorization; 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.TinyDB;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.UserRepositories;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import retrofit2.Call; import retrofit2.Call;
@ -44,8 +45,8 @@ public class RepoForksActivity extends BaseActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private TextView noData; private TextView noData;
private ProgressBar progressBar; private ProgressBar progressBar;
private String TAG = "RepositoryForks"; private final String TAG = "RepositoryForks";
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
private int pageSize = 1; private int pageSize = 1;
private RecyclerView recyclerView; private RecyclerView recyclerView;
@ -53,19 +54,16 @@ public class RepoForksActivity extends BaseActivity {
private RepoForksAdapter adapter; private RepoForksAdapter adapter;
private ProgressBar progressLoadMore; private ProgressBar progressLoadMore;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_forks;
}
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Toolbar toolbar = findViewById(R.id.toolbar); ActivityRepoForksBinding activityRepoForksBinding = ActivityRepoForksBinding.inflate(getLayoutInflater());
setContentView(activityRepoForksBinding.getRoot());
Toolbar toolbar = activityRepoForksBinding.toolbar;
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
TinyDB tinyDb = TinyDB.getInstance(appCtx); TinyDB tinyDb = TinyDB.getInstance(appCtx);
@ -76,15 +74,15 @@ public class RepoForksActivity extends BaseActivity {
final String repoOwner = parts[0]; final String repoOwner = parts[0];
final String repoName = parts[1]; 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.setMovementMethod(new ScrollingMovementMethod());
toolbar_title.setText(String.format("%s : %s", ctx.getResources().getString(R.string.infoTabRepoForksCount), repoName)); toolbar_title.setText(String.format("%s : %s", ctx.getResources().getString(R.string.infoTabRepoForksCount), repoName));
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = activityRepoForksBinding.close;
noData = findViewById(R.id.noData); noData = activityRepoForksBinding.noData;
progressLoadMore = findViewById(R.id.progressLoadMore); progressLoadMore = activityRepoForksBinding.progressLoadMore;
progressBar = findViewById(R.id.progress_bar); progressBar = activityRepoForksBinding.progressBar;
SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh); SwipeRefreshLayout swipeRefresh = activityRepoForksBinding.pullToRefresh;
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
@ -92,10 +90,10 @@ public class RepoForksActivity extends BaseActivity {
// if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances) // if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances)
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12")) { 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<>(); forksList = new ArrayList<>();
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),

View File

@ -9,6 +9,7 @@ import android.widget.TextView;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoStargazersAdapter; import org.mian.gitnex.adapters.RepoStargazersAdapter;
import org.mian.gitnex.databinding.ActivityRepoStargazersBinding;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.viewmodels.RepoStargazersViewModel; import org.mian.gitnex.viewmodels.RepoStargazersViewModel;
@ -24,21 +25,19 @@ public class RepoStargazersActivity extends BaseActivity {
private GridView mGridView; private GridView mGridView;
private ProgressBar mProgressBar; private ProgressBar mProgressBar;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repo_stargazers;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ImageView closeActivity = findViewById(R.id.close); ActivityRepoStargazersBinding activityRepoStargazersBinding = ActivityRepoStargazersBinding.inflate(getLayoutInflater());
TextView toolbarTitle = findViewById(R.id.toolbar_title); setContentView(activityRepoStargazersBinding.getRoot());
noDataStargazers = findViewById(R.id.noDataStargazers);
mGridView = findViewById(R.id.gridView); ImageView closeActivity = activityRepoStargazersBinding.close;
mProgressBar = findViewById(R.id.progress_bar); TextView toolbarTitle = activityRepoStargazersBinding.toolbarTitle;
noDataStargazers = activityRepoStargazersBinding.noDataStargazers;
mGridView = activityRepoStargazersBinding.gridView;
mProgressBar = activityRepoStargazersBinding.progressBar;
String repoFullNameForStars = getIntent().getStringExtra("repoFullNameForStars"); String repoFullNameForStars = getIntent().getStringExtra("repoFullNameForStars");
String[] parts = repoFullNameForStars.split("/"); String[] parts = repoFullNameForStars.split("/");

View File

@ -9,6 +9,7 @@ import android.widget.TextView;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoWatchersAdapter; import org.mian.gitnex.adapters.RepoWatchersAdapter;
import org.mian.gitnex.databinding.ActivityRepoWatchersBinding;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.viewmodels.RepoWatchersViewModel; import org.mian.gitnex.viewmodels.RepoWatchersViewModel;
@ -24,21 +25,19 @@ public class RepoWatchersActivity extends BaseActivity {
private GridView mGridView; private GridView mGridView;
private ProgressBar mProgressBar; private ProgressBar mProgressBar;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repo_watchers;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ImageView closeActivity = findViewById(R.id.close); ActivityRepoWatchersBinding activityRepoWatchersBinding = ActivityRepoWatchersBinding.inflate(getLayoutInflater());
TextView toolbarTitle = findViewById(R.id.toolbar_title); setContentView(activityRepoWatchersBinding.getRoot());
noDataWatchers = findViewById(R.id.noDataWatchers);
mGridView = findViewById(R.id.gridView); ImageView closeActivity = activityRepoWatchersBinding.close;
mProgressBar = findViewById(R.id.progress_bar); TextView toolbarTitle = activityRepoWatchersBinding.toolbarTitle;
noDataWatchers = activityRepoWatchersBinding.noDataWatchers;
mGridView = activityRepoWatchersBinding.gridView;
mProgressBar = activityRepoWatchersBinding.progressBar;
String repoFullNameForWatchers = getIntent().getStringExtra("repoFullNameForWatchers"); String repoFullNameForWatchers = getIntent().getStringExtra("repoFullNameForWatchers");
String[] parts = repoFullNameForWatchers.split("/"); String[] parts = repoFullNameForWatchers.split("/");

View File

@ -10,8 +10,11 @@ import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.gson.JsonElement; 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.R;
import org.mian.gitnex.clients.RetrofitClient; 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.RepositoriesApi;
import org.mian.gitnex.databinding.ActivityRepositorySettingsBinding; import org.mian.gitnex.databinding.ActivityRepositorySettingsBinding;
import org.mian.gitnex.databinding.CustomRepositoryDeleteDialogBinding; import org.mian.gitnex.databinding.CustomRepositoryDeleteDialogBinding;
@ -19,8 +22,6 @@ import org.mian.gitnex.databinding.CustomRepositoryEditPropertiesDialogBinding;
import org.mian.gitnex.databinding.CustomRepositoryTransferDialogBinding; import org.mian.gitnex.databinding.CustomRepositoryTransferDialogBinding;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.RepositoryTransfer;
import org.mian.gitnex.models.UserRepositories;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -45,19 +46,13 @@ public class RepositorySettingsActivity extends BaseActivity {
private String repositoryOwner; private String repositoryOwner;
private String repositoryName; private String repositoryName;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repository_settings;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewBinding = ActivityRepositorySettingsBinding.inflate(getLayoutInflater()); viewBinding = ActivityRepositorySettingsBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot(); setContentView(viewBinding.getRoot());
setContentView(view);
loginUid = tinyDB.getString("loginUid"); loginUid = tinyDB.getString("loginUid");
String repoFullName = tinyDB.getString("repoFullName"); String repoFullName = tinyDB.getString("repoFullName");
@ -119,6 +114,7 @@ public class RepositorySettingsActivity extends BaseActivity {
} }
}); });
dialogTransferRepository.setCancelable(false);
dialogTransferRepository.show(); dialogTransferRepository.show();
} }
@ -144,7 +140,7 @@ public class RepositorySettingsActivity extends BaseActivity {
Toasty.success(ctx, getString(R.string.repoTransferSuccess)); Toasty.success(ctx, getString(R.string.repoTransferSuccess));
finish(); 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); Intent intent = new Intent(RepositorySettingsActivity.this, MainActivity.class);
RepositorySettingsActivity.this.startActivity(intent); RepositorySettingsActivity.this.startActivity(intent);
} }
@ -201,6 +197,7 @@ public class RepositorySettingsActivity extends BaseActivity {
} }
}); });
dialogDeleteRepository.setCancelable(false);
dialogDeleteRepository.show(); dialogDeleteRepository.show();
} }
@ -224,7 +221,7 @@ public class RepositorySettingsActivity extends BaseActivity {
Toasty.success(ctx, getString(R.string.repoDeletionSuccess)); Toasty.success(ctx, getString(R.string.repoDeletionSuccess));
finish(); 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); Intent intent = new Intent(RepositorySettingsActivity.this, MainActivity.class);
RepositorySettingsActivity.this.startActivity(intent); RepositorySettingsActivity.this.startActivity(intent);
} }
@ -340,6 +337,7 @@ public class RepositorySettingsActivity extends BaseActivity {
propBinding.repoEnableMerge.isChecked(), propBinding.repoEnableRebase.isChecked(), propBinding.repoEnableMerge.isChecked(), propBinding.repoEnableRebase.isChecked(),
propBinding.repoEnableSquash.isChecked(), propBinding.repoEnableForceMerge.isChecked())); propBinding.repoEnableSquash.isChecked(), propBinding.repoEnableForceMerge.isChecked()));
dialogProp.setCancelable(false);
dialogProp.show(); dialogProp.show();
} }
@ -386,7 +384,7 @@ public class RepositorySettingsActivity extends BaseActivity {
if(!repositoryName.equals(repoName)) { if(!repositoryName.equals(repoName)) {
finish(); 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); Intent intent = new Intent(RepositorySettingsActivity.this, MainActivity.class);
RepositorySettingsActivity.this.startActivity(intent); RepositorySettingsActivity.this.startActivity(intent);
} }

View File

@ -1,13 +1,20 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Bundle; import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TimePicker;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.switchmaterial.SwitchMaterial; import com.google.android.material.switchmaterial.SwitchMaterial;
import org.jetbrains.annotations.NotNull;
import org.mian.gitnex.R; 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.Toasty;
/** /**
@ -18,70 +25,70 @@ public class SettingsAppearanceActivity extends BaseActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private static final String[] timeList = {"Pretty", "Normal"}; private static String[] timeList;
private static int timeSelectedChoice = 0; private static int timeSelectedChoice = 0;
private static final String[] customFontList = {"Roboto", "Manrope", "Source Code Pro"}; private static String[] customFontList;
private static int customFontSelectedChoice = 0; private static int customFontSelectedChoice = 0;
private static final String[] themeList = {"Dark", "Light", "Auto (Light / Dark)", "Retro", "Auto (Retro / Dark)", "Pitch Black"}; private static String[] themeList;
private static int themeSelectedChoice = 0; private static int themeSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_appearance;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ImageView closeActivity = findViewById(R.id.close); ActivitySettingsAppearanceBinding activitySettingsAppearanceBinding = ActivitySettingsAppearanceBinding.inflate(getLayoutInflater());
setContentView(activitySettingsAppearanceBinding.getRoot());
final TextView tvDateTimeSelected = findViewById(R.id.tvDateTimeSelected); // setter for time ImageView closeActivity = activitySettingsAppearanceBinding.close;
final TextView customFontSelected = findViewById(R.id.customFontSelected); // setter for custom font
final TextView themeSelected = findViewById(R.id.themeSelected); // setter for theme
LinearLayout timeFrame = findViewById(R.id.timeFrame); LinearLayout timeFrame = activitySettingsAppearanceBinding.timeFrame;
LinearLayout customFontFrame = findViewById(R.id.customFontFrame); LinearLayout customFontFrame = activitySettingsAppearanceBinding.customFontFrame;
LinearLayout themeFrame = findViewById(R.id.themeSelectionFrame); LinearLayout themeFrame = activitySettingsAppearanceBinding.themeSelectionFrame;
LinearLayout lightTimeFrame = activitySettingsAppearanceBinding.lightThemeTimeSelectionFrame;
LinearLayout darkTimeFrame = activitySettingsAppearanceBinding.darkThemeTimeSelectionFrame;
SwitchMaterial counterBadgesSwitch = findViewById(R.id.switchCounterBadge); SwitchMaterial counterBadgesSwitch = activitySettingsAppearanceBinding.switchCounterBadge;
timeList = getResources().getStringArray(R.array.timeFormats);
customFontList = getResources().getStringArray(R.array.fonts);
themeList = getResources().getStringArray(R.array.themes);
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
if(!tinyDB.getString("timeStr").isEmpty()) { 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;
tvDateTimeSelected.setText(tinyDB.getString("timeStr")); 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;
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("themeStr").startsWith("Auto")) {
darkTimeFrame.setVisibility(View.VISIBLE);
lightTimeFrame.setVisibility(View.VISIBLE);
} }
else {
if(!tinyDB.getString("customFontStr").isEmpty()) { darkTimeFrame.setVisibility(View.GONE);
lightTimeFrame.setVisibility(View.GONE);
customFontSelected.setText(tinyDB.getString("customFontStr"));
} }
if(!tinyDB.getString("themeStr").isEmpty()) {
themeSelected.setText(tinyDB.getString("themeStr"));
}
if(timeSelectedChoice == 0) {
timeSelectedChoice = tinyDB.getInt("timeId"); timeSelectedChoice = tinyDB.getInt("timeId");
}
if(customFontSelectedChoice == 0) {
customFontSelectedChoice = tinyDB.getInt("customFontId", 1); customFontSelectedChoice = tinyDB.getInt("customFontId", 1);
}
if(themeSelectedChoice == 0) {
themeSelectedChoice = tinyDB.getInt("themeId"); themeSelectedChoice = tinyDB.getInt("themeId");
}
counterBadgesSwitch.setChecked(tinyDB.getBoolean("enableCounterBadges")); counterBadgesSwitch.setChecked(tinyDB.getBoolean("enableCounterBadges"));
@ -103,7 +110,7 @@ public class SettingsAppearanceActivity extends BaseActivity {
tsBuilder.setSingleChoiceItems(themeList, themeSelectedChoice, (dialogInterfaceTheme, i) -> { tsBuilder.setSingleChoiceItems(themeList, themeSelectedChoice, (dialogInterfaceTheme, i) -> {
themeSelectedChoice = i; themeSelectedChoice = i;
themeSelected.setText(themeList[i]); activitySettingsAppearanceBinding.themeSelected.setText(themeList[i]);
tinyDB.putString("themeStr", themeList[i]); tinyDB.putString("themeStr", themeList[i]);
tinyDB.putInt("themeId", i); tinyDB.putInt("themeId", i);
@ -118,6 +125,16 @@ public class SettingsAppearanceActivity extends BaseActivity {
cfDialog.show(); 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 // custom font dialog
customFontFrame.setOnClickListener(view -> { customFontFrame.setOnClickListener(view -> {
@ -129,7 +146,7 @@ public class SettingsAppearanceActivity extends BaseActivity {
cfBuilder.setSingleChoiceItems(customFontList, customFontSelectedChoice, (dialogInterfaceCustomFont, i) -> { cfBuilder.setSingleChoiceItems(customFontList, customFontSelectedChoice, (dialogInterfaceCustomFont, i) -> {
customFontSelectedChoice = i; customFontSelectedChoice = i;
customFontSelected.setText(customFontList[i]); activitySettingsAppearanceBinding.customFontSelected.setText(customFontList[i]);
tinyDB.putString("customFontStr", customFontList[i]); tinyDB.putString("customFontStr", customFontList[i]);
tinyDB.putInt("customFontId", i); tinyDB.putInt("customFontId", i);
@ -155,17 +172,17 @@ public class SettingsAppearanceActivity extends BaseActivity {
tBuilder.setSingleChoiceItems(timeList, timeSelectedChoice, (dialogInterfaceTime, i) -> { tBuilder.setSingleChoiceItems(timeList, timeSelectedChoice, (dialogInterfaceTime, i) -> {
timeSelectedChoice = i; timeSelectedChoice = i;
tvDateTimeSelected.setText(timeList[i]); activitySettingsAppearanceBinding.tvDateTimeSelected.setText(timeList[i]);
tinyDB.putString("timeStr", timeList[i]); tinyDB.putString("timeStr", timeList[i]);
tinyDB.putInt("timeId", i); tinyDB.putInt("timeId", i);
if("Normal".equals(timeList[i])) { switch(i) {
case 0:
tinyDB.putString("dateFormat", "normal");
}
else {
tinyDB.putString("dateFormat", "pretty"); tinyDB.putString("dateFormat", "pretty");
break;
case 1:
tinyDB.putString("dateFormat", "normal");
break;
} }
dialogInterfaceTime.dismiss(); dialogInterfaceTime.dismiss();
@ -182,4 +199,54 @@ public class SettingsAppearanceActivity extends BaseActivity {
onClickListener = view -> finish(); 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

@ -3,8 +3,8 @@ package org.mian.gitnex.activities;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import com.google.android.material.switchmaterial.SwitchMaterial;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsDraftsBinding;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
/** /**
@ -15,28 +15,23 @@ public class SettingsDraftsActivity extends BaseActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_drafts;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ImageView closeActivity = findViewById(R.id.close); ActivitySettingsDraftsBinding activitySettingsDraftsBinding = ActivitySettingsDraftsBinding.inflate(getLayoutInflater());
setContentView(activitySettingsDraftsBinding.getRoot());
ImageView closeActivity = activitySettingsDraftsBinding.close;
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
SwitchMaterial commentsDeletionSwitch = findViewById(R.id.commentsDeletionSwitch); activitySettingsDraftsBinding.commentsDeletionSwitch.setChecked(tinyDB.getBoolean("draftsCommentsDeletionEnabled"));
commentsDeletionSwitch.setChecked(tinyDB.getBoolean("draftsCommentsDeletionEnabled"));
// delete comments on submit switcher // delete comments on submit switcher
commentsDeletionSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { activitySettingsDraftsBinding.commentsDeletionSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
tinyDB.putBoolean("draftsCommentsDeletionEnabled", isChecked); tinyDB.putBoolean("draftsCommentsDeletionEnabled", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave)); Toasty.success(appCtx, getResources().getString(R.string.settingsSave));

View File

@ -1,93 +0,0 @@
package org.mian.gitnex.activities;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import com.google.android.material.switchmaterial.SwitchMaterial;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Toasty;
/**
* Author M M Arif
*/
public class SettingsFileViewerActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private static final 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);
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);
SwitchMaterial pdfModeSwitch = findViewById(R.id.switchPdfMode);
if(!tinyDB.getString("fileviewerSourceCodeThemeStr").isEmpty()) {
fileViewerSourceCodeThemesSelected.setText(tinyDB.getString("fileviewerSourceCodeThemeStr"));
}
if(fileViewerSourceCodeThemesSelectedChoice == 0) {
fileViewerSourceCodeThemesSelectedChoice = tinyDB.getInt("fileviewerThemeId");
}
pdfModeSwitch.setChecked(tinyDB.getBoolean("enablePdfMode"));
// fileviewer srouce code theme selection dialog
sourceCodeThemeFrame.setOnClickListener(view -> {
AlertDialog.Builder fvtsBuilder = new AlertDialog.Builder(SettingsFileViewerActivity.this);
fvtsBuilder.setTitle(R.string.fileviewerSourceCodeThemeSelectorDialogTitle);
fvtsBuilder.setCancelable(fileViewerSourceCodeThemesSelectedChoice != -1);
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) -> {
tinyDB.putBoolean("enablePdfMode", isChecked);
tinyDB.putString("enablePdfModeInit", "yes");
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -23,42 +23,31 @@ public class SettingsGeneralActivity extends BaseActivity {
private List<String> homeScreenList; private List<String> homeScreenList;
private static int homeScreenSelectedChoice = 0; private static int homeScreenSelectedChoice = 0;
private List<String> defaultScreen; private List<String> linkHandlerDefaultScreen;
private static int defaultLinkHandlerScreenSelectedChoice = 0; private static int defaultLinkHandlerScreenSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_general;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewBinding = ActivitySettingsGeneralBinding.inflate(getLayoutInflater()); viewBinding = ActivitySettingsGeneralBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot(); setContentView(viewBinding.getRoot());
setContentView(view);
initCloseListener(); initCloseListener();
viewBinding.close.setOnClickListener(onClickListener); viewBinding.close.setOnClickListener(onClickListener);
// home screen // home screen
String[] homeDefaultScreen_ = {getResources().getString(R.string.pageTitleMyRepos), getResources().getString(R.string.pageTitleStarredRepos), getResources().getString(R.string.pageTitleOrganizations), String[] appHomeDefaultScreen = getResources().getStringArray(R.array.appDefaultHomeScreen);
getResources().getString(R.string.pageTitleRepositories), getResources().getString(R.string.pageTitleProfile), getResources().getString(R.string.pageTitleExplore),
getResources().getString(R.string.titleDrafts)};
String[] homeDefaultScreenNew = {getResources().getString(R.string.pageTitleMyRepos), getResources().getString(R.string.pageTitleStarredRepos), getResources().getString(R.string.pageTitleOrganizations), String[] appHomeDefaultScreenNew = getResources().getStringArray(R.array.appDefaultHomeScreenNew);
getResources().getString(R.string.pageTitleRepositories), getResources().getString(R.string.pageTitleProfile), getResources().getString(R.string.pageTitleExplore),
getResources().getString(R.string.titleDrafts), getResources().getString(R.string.pageTitleNotifications)};
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.3")) { if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.3")) {
homeDefaultScreen_ = homeDefaultScreenNew; appHomeDefaultScreen = appHomeDefaultScreenNew;
} }
homeScreenList = new ArrayList<>(Arrays.asList(homeDefaultScreen_)); homeScreenList = new ArrayList<>(Arrays.asList(appHomeDefaultScreen));
String[] homeScreenArray = new String[homeScreenList.size()]; String[] homeScreenArray = new String[homeScreenList.size()];
homeScreenList.toArray(homeScreenArray); homeScreenList.toArray(homeScreenArray);
@ -120,34 +109,14 @@ public class SettingsGeneralActivity extends BaseActivity {
// home screen // home screen
// link handler // link handler
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)}; String[] linkHandlerDefaultScreenList = getResources().getStringArray(R.array.linkHandlerDefaultScreen);
defaultScreen = new ArrayList<>(Arrays.asList(defaultScreen_)); linkHandlerDefaultScreen = new ArrayList<>(Arrays.asList(linkHandlerDefaultScreenList));
String[] linksArray = new String[defaultScreen.size()]; String[] linksArray = new String[linkHandlerDefaultScreen.size()];
defaultScreen.toArray(linksArray); linkHandlerDefaultScreen.toArray(linksArray);
if(defaultLinkHandlerScreenSelectedChoice == 0) {
defaultLinkHandlerScreenSelectedChoice = tinyDB.getInt("defaultScreenId"); defaultLinkHandlerScreenSelectedChoice = tinyDB.getInt("defaultScreenId");
viewBinding.generalDeepLinkSelected.setText(getResources().getString(R.string.generalDeepLinkSelectedText)); viewBinding.generalDeepLinkSelected.setText(linksArray[defaultLinkHandlerScreenSelectedChoice]);
}
if(defaultLinkHandlerScreenSelectedChoice == 1) {
viewBinding.generalDeepLinkSelected.setText(getResources().getString(R.string.navRepos));
}
else if(defaultLinkHandlerScreenSelectedChoice == 2) {
viewBinding.generalDeepLinkSelected.setText(getResources().getString(R.string.navOrgs));
}
else if(defaultLinkHandlerScreenSelectedChoice == 3) {
viewBinding.generalDeepLinkSelected.setText(getResources().getString(R.string.pageTitleNotifications));
}
else if(defaultLinkHandlerScreenSelectedChoice == 4) {
viewBinding.generalDeepLinkSelected.setText(getResources().getString(R.string.navExplore));
}
viewBinding.setDefaultLinkHandler.setOnClickListener(setDefaultLinkHandler -> { viewBinding.setDefaultLinkHandler.setOnClickListener(setDefaultLinkHandler -> {

View File

@ -8,9 +8,9 @@ import androidx.appcompat.app.AlertDialog;
import com.pes.androidmaterialcolorpickerdialog.ColorPicker; import com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsNotificationsBinding; import org.mian.gitnex.databinding.ActivitySettingsNotificationsBinding;
import org.mian.gitnex.helpers.StaticGlobalVariables; import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.notifications.NotificationsMaster; import org.mian.gitnex.notifications.Notifications;
/** /**
* Template Author M M Arif * Template Author M M Arif
@ -21,26 +21,19 @@ public class SettingsNotificationsActivity extends BaseActivity {
private ActivitySettingsNotificationsBinding viewBinding; private ActivitySettingsNotificationsBinding viewBinding;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_notifications;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewBinding = ActivitySettingsNotificationsBinding.inflate(getLayoutInflater()); viewBinding = ActivitySettingsNotificationsBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot(); setContentView(viewBinding.getRoot());
setContentView(view);
View.OnClickListener onClickListener = viewClose -> finish(); View.OnClickListener onClickListener = viewClose -> finish();
viewBinding.close.setOnClickListener(onClickListener); viewBinding.close.setOnClickListener(onClickListener);
viewBinding.pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), tinyDB.getInt("pollingDelayMinutes", StaticGlobalVariables.defaultPollingDelay))); viewBinding.pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay)));
viewBinding.chooseColorState.setCardBackgroundColor(tinyDB.getInt("notificationsLightColor", Color.GREEN)); viewBinding.chooseColorState.setCardBackgroundColor(tinyDB.getInt("notificationsLightColor", Color.GREEN));
viewBinding.enableNotificationsMode.setChecked(tinyDB.getBoolean("notificationsEnabled", true)); viewBinding.enableNotificationsMode.setChecked(tinyDB.getBoolean("notificationsEnabled", true));
@ -50,7 +43,13 @@ public class SettingsNotificationsActivity extends BaseActivity {
viewBinding.enableNotificationsMode.setOnCheckedChangeListener((buttonView, isChecked) -> { viewBinding.enableNotificationsMode.setOnCheckedChangeListener((buttonView, isChecked) -> {
tinyDB.putBoolean("notificationsEnabled", isChecked); tinyDB.putBoolean("notificationsEnabled", isChecked);
if(!isChecked) NotificationsMaster.fireWorker(ctx);
if(isChecked) {
Notifications.startWorker(ctx);
} else {
Notifications.stopWorker(ctx);
}
Toasty.info(appCtx, getResources().getString(R.string.settingsSave)); Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
}); });
@ -59,9 +58,9 @@ public class SettingsNotificationsActivity extends BaseActivity {
viewBinding.pollingDelayFrame.setOnClickListener(v -> { viewBinding.pollingDelayFrame.setOnClickListener(v -> {
NumberPicker numberPicker = new NumberPicker(ctx); NumberPicker numberPicker = new NumberPicker(ctx);
numberPicker.setMinValue(StaticGlobalVariables.minimumPollingDelay); numberPicker.setMinValue(Constants.minimumPollingDelay);
numberPicker.setMaxValue(StaticGlobalVariables.maximumPollingDelay); numberPicker.setMaxValue(Constants.maximumPollingDelay);
numberPicker.setValue(tinyDB.getInt("pollingDelayMinutes", StaticGlobalVariables.defaultPollingDelay)); numberPicker.setValue(tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay));
numberPicker.setWrapSelectorWheel(true); numberPicker.setWrapSelectorWheel(true);
AlertDialog.Builder builder = new AlertDialog.Builder(ctx); AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
@ -73,8 +72,8 @@ public class SettingsNotificationsActivity extends BaseActivity {
tinyDB.putInt("pollingDelayMinutes", numberPicker.getValue()); tinyDB.putInt("pollingDelayMinutes", numberPicker.getValue());
NotificationsMaster.fireWorker(ctx); Notifications.stopWorker(ctx);
NotificationsMaster.hireWorker(ctx); Notifications.startWorker(ctx);
viewBinding.pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), numberPicker.getValue())); viewBinding.pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), numberPicker.getValue()));
Toasty.info(appCtx, getResources().getString(R.string.settingsSave)); Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
@ -83,6 +82,7 @@ public class SettingsNotificationsActivity extends BaseActivity {
builder.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss()); builder.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss());
builder.setView(numberPicker); builder.setView(numberPicker);
builder.create().show(); builder.create().show();
}); });
// lights switcher // lights switcher

View File

@ -3,8 +3,8 @@ package org.mian.gitnex.activities;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import com.google.android.material.switchmaterial.SwitchMaterial;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsReportsBinding;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
/** /**
@ -15,28 +15,23 @@ public class SettingsReportsActivity extends BaseActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_reporting;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ImageView closeActivity = findViewById(R.id.close); ActivitySettingsReportsBinding activitySettingsReportsBinding = ActivitySettingsReportsBinding.inflate(getLayoutInflater());
setContentView(activitySettingsReportsBinding.getRoot());
ImageView closeActivity = activitySettingsReportsBinding.close;
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
SwitchMaterial crashReportsSwitch = findViewById(R.id.crashReportsSwitch); activitySettingsReportsBinding.crashReportsSwitch.setChecked(tinyDB.getBoolean("crashReportingEnabled"));
crashReportsSwitch.setChecked(tinyDB.getBoolean("crashReportingEnabled"));
// crash reports switcher // crash reports switcher
crashReportsSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { activitySettingsReportsBinding.crashReportsSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
tinyDB.putBoolean("crashReportingEnabled", isChecked); tinyDB.putBoolean("crashReportingEnabled", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave)); Toasty.success(appCtx, getResources().getString(R.string.settingsSave));

View File

@ -1,7 +1,9 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.app.KeyguardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
@ -9,12 +11,17 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.biometric.BiometricManager;
import com.google.android.material.switchmaterial.SwitchMaterial;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsSecurityBinding;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.ssl.MemorizingTrustManager; import org.mian.gitnex.helpers.ssl.MemorizingTrustManager;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG;
import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL;
/** /**
* Author M M Arif * Author M M Arif
@ -24,36 +31,38 @@ public class SettingsSecurityActivity extends BaseActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private static final String[] cacheSizeDataList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"}; private static String[] cacheSizeDataList;
private static int cacheSizeDataSelectedChoice = 0; private static int cacheSizeDataSelectedChoice = 0;
private static final String[] cacheSizeImagesList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"}; private static String[] cacheSizeImagesList;
private static int cacheSizeImagesSelectedChoice = 0; private static int cacheSizeImagesSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_security;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ImageView closeActivity = findViewById(R.id.close); ActivitySettingsSecurityBinding activitySettingsSecurityBinding = ActivitySettingsSecurityBinding.inflate(getLayoutInflater());
setContentView(activitySettingsSecurityBinding.getRoot());
ImageView closeActivity = activitySettingsSecurityBinding.close;
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
TextView cacheSizeDataSelected = findViewById(R.id.cacheSizeDataSelected); // setter for data cache size TextView cacheSizeDataSelected = activitySettingsSecurityBinding.cacheSizeDataSelected; // setter for data cache size
TextView cacheSizeImagesSelected = findViewById(R.id.cacheSizeImagesSelected); // setter for images cache size TextView cacheSizeImagesSelected = activitySettingsSecurityBinding.cacheSizeImagesSelected; // setter for images cache size
TextView clearCacheSelected = findViewById(R.id.clearCacheSelected); // setter for clear cache TextView clearCacheSelected = activitySettingsSecurityBinding.clearCacheSelected; // setter for clear cache
LinearLayout certsFrame = findViewById(R.id.certsFrame); LinearLayout certsFrame = activitySettingsSecurityBinding.certsFrame;
LinearLayout cacheSizeDataFrame = findViewById(R.id.cacheSizeDataSelectionFrame); LinearLayout cacheSizeDataFrame = activitySettingsSecurityBinding.cacheSizeDataSelectionFrame;
LinearLayout cacheSizeImagesFrame = findViewById(R.id.cacheSizeImagesSelectionFrame); LinearLayout cacheSizeImagesFrame = activitySettingsSecurityBinding.cacheSizeImagesSelectionFrame;
LinearLayout clearCacheFrame = findViewById(R.id.clearCacheSelectionFrame); LinearLayout clearCacheFrame = activitySettingsSecurityBinding.clearCacheSelectionFrame;
SwitchMaterial switchBiometric = activitySettingsSecurityBinding.switchBiometric;
cacheSizeDataList = getResources().getStringArray(R.array.cacheSizeList);
cacheSizeImagesList = getResources().getStringArray(R.array.cacheSizeList);
if(!tinyDB.getString("cacheSizeStr").isEmpty()) { if(!tinyDB.getString("cacheSizeStr").isEmpty()) {
@ -75,6 +84,70 @@ public class SettingsSecurityActivity extends BaseActivity {
cacheSizeImagesSelectedChoice = tinyDB.getInt("cacheSizeImagesId"); cacheSizeImagesSelectedChoice = tinyDB.getInt("cacheSizeImagesId");
} }
switchBiometric.setChecked(tinyDB.getBoolean("biometricStatus"));
// 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 // clear cache setter
File cacheDir = appCtx.getCacheDir(); File cacheDir = appCtx.getCacheDir();
clearCacheSelected.setText(FileUtils.byteCountToDisplaySize((int) FileUtils.sizeOfDirectory(cacheDir))); clearCacheSelected.setText(FileUtils.byteCountToDisplaySize((int) FileUtils.sizeOfDirectory(cacheDir)));

View File

@ -9,7 +9,11 @@ import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsTranslationBinding;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.TreeMap;
/** /**
* Author M M Arif * Author M M Arif
@ -19,30 +23,31 @@ public class SettingsTranslationActivity extends BaseActivity {
private View.OnClickListener onClickListener; 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; private static int langSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_translation;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ImageView closeActivity = findViewById(R.id.close); 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));
}
ActivitySettingsTranslationBinding activitySettingsTranslationBinding = ActivitySettingsTranslationBinding.inflate(getLayoutInflater());
setContentView(activitySettingsTranslationBinding.getRoot());
ImageView closeActivity = activitySettingsTranslationBinding.close;
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
final TextView tvLanguageSelected = findViewById(R.id.tvLanguageSelected); // setter for en, fr final TextView tvLanguageSelected = activitySettingsTranslationBinding.tvLanguageSelected; // setter for en, fr
TextView helpTranslate = findViewById(R.id.helpTranslate); TextView helpTranslate = activitySettingsTranslationBinding.helpTranslate;
LinearLayout langFrame = findViewById(R.id.langFrame); LinearLayout langFrame = activitySettingsTranslationBinding.langFrame;
helpTranslate.setOnClickListener(v12 -> { helpTranslate.setOnClickListener(v12 -> {
@ -54,15 +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 // language dialog
langFrame.setOnClickListener(view -> { langFrame.setOnClickListener(view -> {
@ -72,89 +71,18 @@ public class SettingsTranslationActivity extends BaseActivity {
lBuilder.setTitle(R.string.settingsLanguageSelectorDialogTitle); lBuilder.setTitle(R.string.settingsLanguageSelectorDialogTitle);
lBuilder.setCancelable(langSelectedChoice != -1); lBuilder.setCancelable(langSelectedChoice != -1);
lBuilder.setSingleChoiceItems(langList, langSelectedChoice, (dialogInterface, i) -> { lBuilder.setSingleChoiceItems(langs.values().toArray(new String[0]), langSelectedChoice, (dialogInterface, i) -> {
langSelectedChoice = i; String selectedLanguage = langs.keySet().toArray(new String[0])[i];
tvLanguageSelected.setText(langList[i]); tinyDB.putString("localeStr", langs.get(selectedLanguage));
tinyDB.putString("localeStr", langList[i]);
tinyDB.putInt("langId", i); 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); tinyDB.putBoolean("refreshParent", true);
this.recreate();
this.overridePendingTransition(0, 0); this.overridePendingTransition(0, 0);
dialogInterface.dismiss(); dialogInterface.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave)); Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
this.recreate();
}); });
lBuilder.setNeutralButton(getString(R.string.cancelButton), null); lBuilder.setNeutralButton(getString(R.string.cancelButton), null);
@ -169,4 +97,10 @@ public class SettingsTranslationActivity extends BaseActivity {
onClickListener = view -> finish(); 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; package org.mian.gitnex.adapters;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -9,12 +11,15 @@ import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -24,19 +29,22 @@ import java.util.List;
public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdapter.UsersViewHolder> implements Filterable { public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdapter.UsersViewHolder> implements Filterable {
private List<UserInfo> usersList; private final List<UserInfo> usersList;
private Context mCtx; private final Context context;
private List<UserInfo> usersListFull; private final List<UserInfo> usersListFull;
static class UsersViewHolder extends RecyclerView.ViewHolder { class UsersViewHolder extends RecyclerView.ViewHolder {
private ImageView userAvatar; private String userLoginId;
private TextView userFullName;
private TextView userEmail; private final ImageView userAvatar;
private ImageView userRole; private final TextView userFullName;
private TextView userName; private final TextView userEmail;
private final ImageView userRole;
private final TextView userName;
private UsersViewHolder(View itemView) { private UsersViewHolder(View itemView) {
super(itemView); super(itemView);
userAvatar = itemView.findViewById(R.id.userAvatar); userAvatar = itemView.findViewById(R.id.userAvatar);
@ -45,11 +53,22 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
userEmail = itemView.findViewById(R.id.userEmail); userEmail = itemView.findViewById(R.id.userEmail);
userRole = itemView.findViewById(R.id.userRole); 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) { public AdminGetUsersAdapter(Context ctx, List<UserInfo> usersListMain) {
this.mCtx = mCtx;
this.context = ctx;
this.usersList = usersListMain; this.usersList = usersListMain;
usersListFull = new ArrayList<>(usersList); usersListFull = new ArrayList<>(usersList);
} }
@ -57,6 +76,7 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
@NonNull @NonNull
@Override @Override
public AdminGetUsersAdapter.UsersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public AdminGetUsersAdapter.UsersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_admin_users, parent, false); View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_admin_users, parent, false);
return new AdminGetUsersAdapter.UsersViewHolder(v); 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) { public void onBindViewHolder(@NonNull AdminGetUsersAdapter.UsersViewHolder holder, int position) {
UserInfo currentItem = usersList.get(position); UserInfo currentItem = usersList.get(position);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
holder.userLoginId = currentItem.getLogin();
if(!currentItem.getFullname().equals("")) { 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 { 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); holder.userName.setVisibility(View.GONE);
} }
if(!currentItem.getEmail().equals("")) { if(!currentItem.getEmail().equals("")) {
holder.userEmail.setText(currentItem.getEmail()); holder.userEmail.setText(currentItem.getEmail());
} }
else { else {
holder.userEmail.setVisibility(View.GONE); holder.userEmail.setVisibility(View.GONE);
} }
if(currentItem.getIs_admin()) { if(currentItem.getIs_admin()) {
holder.userRole.setVisibility(View.VISIBLE); holder.userRole.setVisibility(View.VISIBLE);
TextDrawable drawable = TextDrawable.builder() TextDrawable drawable = TextDrawable.builder()
.beginConfig() .beginConfig()
.textColor(mCtx.getResources().getColor(R.color.colorWhite)) .textColor(ResourcesCompat.getColor(context.getResources(), R.color.colorWhite, null))
.fontSize(44) .fontSize(44)
.width(180) .width(180)
.height(60) .height(60)
.endConfig() .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); holder.userRole.setImageDrawable(drawable);
} }
else { else {
holder.userRole.setVisibility(View.GONE); 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 @Override
@ -111,14 +140,15 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
return usersFilter; return usersFilter;
} }
private Filter usersFilter = new Filter() { private final Filter usersFilter = new Filter() {
@Override @Override
protected FilterResults performFiltering(CharSequence constraint) { protected FilterResults performFiltering(CharSequence constraint) {
List<UserInfo> filteredList = new ArrayList<>(); List<UserInfo> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) { if (constraint == null || constraint.length() == 0) {
filteredList.addAll(usersListFull); filteredList.addAll(usersListFull);
} else { }
else {
String filterPattern = constraint.toString().toLowerCase().trim(); String filterPattern = constraint.toString().toLowerCase().trim();
for (UserInfo item : usersListFull) { for (UserInfo item : usersListFull) {
@ -136,6 +166,7 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
@Override @Override
protected void publishResults(CharSequence constraint, FilterResults results) { protected void publishResults(CharSequence constraint, FilterResults results) {
usersList.clear(); usersList.clear();
usersList.addAll((List) results.values); usersList.addAll((List) results.values);
notifyDataSetChanged(); notifyDataSetChanged();

View File

@ -1,6 +1,7 @@
package org.mian.gitnex.adapters; package org.mian.gitnex.adapters;
import android.content.Context; import android.content.Context;
import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -9,10 +10,11 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.Collaborators;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.Collaborators;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
@ -23,21 +25,21 @@ import java.util.List;
public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdapter.AssigneesViewHolder> { public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdapter.AssigneesViewHolder> {
private Context mCtx; private final Context context;
private List<Collaborators> assigneesList; private final List<Collaborators> assigneesList;
private List<String> assigneesStrings = new ArrayList<>(); private List<String> assigneesStrings = new ArrayList<>();
private List<String> currentAssignees; private List<String> currentAssignees;
private AssigneesListAdapterListener assigneesListener; private final AssigneesListAdapterListener assigneesListener;
public interface AssigneesListAdapterListener { public interface AssigneesListAdapterListener {
void assigneesInterface(List<String> data); 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.assigneesList = dataMain;
this.assigneesListener = assigneesListener; this.assigneesListener = assigneesListener;
this.currentAssignees = currentAssignees; this.currentAssignees = currentAssignees;
@ -45,9 +47,9 @@ public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdap
static class AssigneesViewHolder extends RecyclerView.ViewHolder { static class AssigneesViewHolder extends RecyclerView.ViewHolder {
private CheckBox assigneesSelection; private final CheckBox assigneesSelection;
private TextView assigneesName; private final TextView assigneesName;
private ImageView assigneesAvatar; private final ImageView assigneesAvatar;
private AssigneesViewHolder(View itemView) { private AssigneesViewHolder(View itemView) {
@ -72,6 +74,7 @@ public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdap
public void onBindViewHolder(@NonNull AssigneesListAdapter.AssigneesViewHolder holder, int position) { public void onBindViewHolder(@NonNull AssigneesListAdapter.AssigneesViewHolder holder, int position) {
Collaborators currentItem = assigneesList.get(position); Collaborators currentItem = assigneesList.get(position);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
if(currentItem.getFull_name().equals("")) { if(currentItem.getFull_name().equals("")) {
@ -79,10 +82,10 @@ public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdap
} }
else { else {
holder.assigneesName.setText(currentItem.getFull_name()); holder.assigneesName.setText(Html.fromHtml(currentItem.getFull_name()));
} }
PicassoService 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++) { for(int i = 0; i < assigneesList.size(); i++) {

View File

@ -2,15 +2,19 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import org.gitnex.tea4j.models.Collaborators;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService; 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 org.mian.gitnex.helpers.RoundedTransformation;
import java.util.List; import java.util.List;
@ -20,22 +24,37 @@ import java.util.List;
public class CollaboratorsAdapter extends BaseAdapter { public class CollaboratorsAdapter extends BaseAdapter {
private List<Collaborators> collaboratorsList; private final List<Collaborators> collaboratorsList;
private Context mCtx; private final Context context;
private class ViewHolder { private class ViewHolder {
private ImageView collaboratorAvatar; private String userLoginId;
private TextView collaboratorName;
private final ImageView collaboratorAvatar;
private final TextView collaboratorName;
ViewHolder(View v) { ViewHolder(View v) {
collaboratorAvatar = v.findViewById(R.id.collaboratorAvatar); collaboratorAvatar = v.findViewById(R.id.collaboratorAvatar);
collaboratorName = v.findViewById(R.id.collaboratorName); 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) { public CollaboratorsAdapter(Context ctx, List<Collaborators> collaboratorsListMain) {
this.mCtx = mCtx;
this.context = ctx;
this.collaboratorsList = collaboratorsListMain; this.collaboratorsList = collaboratorsListMain;
} }
@ -61,28 +80,35 @@ public class CollaboratorsAdapter extends BaseAdapter {
ViewHolder viewHolder = null; ViewHolder viewHolder = null;
if (finalView == 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); viewHolder = new ViewHolder(finalView);
finalView.setTag(viewHolder); finalView.setTag(viewHolder);
} }
else { else {
viewHolder = (ViewHolder) finalView.getTag(); viewHolder = (ViewHolder) finalView.getTag();
} }
initData(viewHolder, position); initData(viewHolder, position);
return finalView; return finalView;
} }
private void initData(ViewHolder viewHolder, int position) { private void initData(ViewHolder viewHolder, int position) {
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
Collaborators currentItem = collaboratorsList.get(position); 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("")) { if(!currentItem.getFull_name().equals("")) {
viewHolder.collaboratorName.setText(currentItem.getFull_name());
viewHolder.collaboratorName.setText(Html.fromHtml(currentItem.getFull_name()));
} }
else { else {
viewHolder.collaboratorName.setText(currentItem.getLogin()); viewHolder.collaboratorName.setText(currentItem.getLogin());
} }

View File

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

@ -4,7 +4,6 @@ import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html;
import android.text.Spanned; import android.text.Spanned;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -12,10 +11,13 @@ import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.text.HtmlCompat;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity; 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.api.DraftsApi;
import org.mian.gitnex.database.models.DraftWithRepository; import org.mian.gitnex.database.models.DraftWithRepository;
import org.mian.gitnex.fragments.BottomSheetReplyFragment; import org.mian.gitnex.fragments.BottomSheetReplyFragment;
@ -32,7 +34,7 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
private List<DraftWithRepository> draftsList; private List<DraftWithRepository> draftsList;
private final FragmentManager fragmentManager; private final FragmentManager fragmentManager;
private final Context mCtx; private final Context context;
class DraftsViewHolder extends RecyclerView.ViewHolder { class DraftsViewHolder extends RecyclerView.ViewHolder {
@ -55,7 +57,9 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
int getDraftId = draftWithRepository.getDraftId(); int getDraftId = draftWithRepository.getDraftId();
deleteDraft(getAdapterPosition()); deleteDraft(getAdapterPosition());
DraftsApi draftsApi = new DraftsApi(mCtx);
DraftsApi draftsApi = BaseApi.getInstance(context, DraftsApi.class);
assert draftsApi != null;
draftsApi.deleteSingleDraft(getDraftId); draftsApi.deleteSingleDraft(getDraftId);
}); });
@ -75,24 +79,23 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
bundle.putString("commentAction", "edit"); bundle.putString("commentAction", "edit");
} }
TinyDB tinyDb = TinyDB.getInstance(mCtx); TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("issueNumber", String.valueOf(draftWithRepository.getIssueId())); tinyDb.putString("issueNumber", String.valueOf(draftWithRepository.getIssueId()));
tinyDb.putLong("repositoryId", draftWithRepository.getRepositoryId()); tinyDb.putLong("repositoryId", draftWithRepository.getRepositoryId());
tinyDb.putString("issueType", draftWithRepository.getIssueType()); tinyDb.putString("issueType", draftWithRepository.getIssueType());
tinyDb.putString("repoFullName", draftWithRepository.getRepositoryOwner() + "/" + draftWithRepository.getRepositoryName()); tinyDb.putString("repoFullName", draftWithRepository.getRepositoryOwner() + "/" + draftWithRepository.getRepositoryName());
BottomSheetReplyFragment bottomSheetReplyFragment = BottomSheetReplyFragment.newInstance(bundle); BottomSheetReplyFragment bottomSheetReplyFragment = BottomSheetReplyFragment.newInstance(bundle);
bottomSheetReplyFragment.setOnInteractedListener(() -> mCtx.startActivity(new Intent(mCtx, IssueDetailActivity.class))); bottomSheetReplyFragment.setOnInteractedListener(() -> context.startActivity(new Intent(context, IssueDetailActivity.class)));
bottomSheetReplyFragment.show(fragmentManager, "replyBottomSheet"); bottomSheetReplyFragment.show(fragmentManager, "replyBottomSheet");
}); });
} }
} }
public DraftsAdapter(Context mCtx, FragmentManager fragmentManager, List<DraftWithRepository> draftsListMain) { public DraftsAdapter(Context ctx, FragmentManager fragmentManager, List<DraftWithRepository> draftsListMain) {
this.mCtx = mCtx; this.context = ctx;
this.fragmentManager = fragmentManager; this.fragmentManager = fragmentManager;
this.draftsList = draftsListMain; this.draftsList = draftsListMain;
} }
@ -102,8 +105,7 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
draftsList.remove(position); draftsList.remove(position);
notifyItemRemoved(position); notifyItemRemoved(position);
notifyItemRangeChanged(position, draftsList.size()); notifyItemRangeChanged(position, draftsList.size());
Toasty.success(mCtx, mCtx.getResources().getString(R.string.draftsSingleDeleteSuccess)); Toasty.success(context, context.getResources().getString(R.string.draftsSingleDeleteSuccess));
} }
@NonNull @NonNull
@ -119,13 +121,14 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
DraftWithRepository currentItem = draftsList.get(position); DraftWithRepository currentItem = draftsList.get(position);
String issueNumber = "<font color='" + mCtx.getResources().getColor(R.color.lightGray) + "'>" + mCtx.getResources().getString(R.string.hash) + currentItem.getIssueId() + "</font>"; String issueNumber = "<font color='" + ResourcesCompat.getColor(context.getResources(), R.color.lightGray, null) + "'>" + context.getResources().getString(R.string.hash) + currentItem.getIssueId() + "</font>";
Spanned headTitle = Html.fromHtml(issueNumber + " " + currentItem.getRepositoryOwner() + " / " + currentItem.getRepositoryName()); Spanned headTitle = HtmlCompat
.fromHtml(issueNumber + " " + currentItem.getRepositoryOwner() + " / " + currentItem.getRepositoryName(), HtmlCompat.FROM_HTML_MODE_LEGACY);
holder.repoInfo.setText(headTitle); holder.repoInfo.setText(headTitle);
holder.draftWithRepository = currentItem; holder.draftWithRepository = currentItem;
new Markdown(mCtx, currentItem.getDraftText(), holder.draftText); Markdown.render(context, currentItem.getDraftText(), holder.draftText);
if(!currentItem.getCommentId().equalsIgnoreCase("new")) { if(!currentItem.getCommentId().equalsIgnoreCase("new")) {
holder.editCommentStatus.setVisibility(View.VISIBLE); holder.editCommentStatus.setVisibility(View.VISIBLE);

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; package org.mian.gitnex.adapters;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Typeface; import android.graphics.Typeface;
@ -11,30 +9,31 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator; 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.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity; 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.PicassoService;
import org.mian.gitnex.clients.RetrofitClient; 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.RepositoriesApi;
import org.mian.gitnex.database.models.Repository; 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.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories; import org.ocpsoft.prettytime.PrettyTime;
import org.mian.gitnex.models.WatchInfo; import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Locale;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -42,87 +41,121 @@ import retrofit2.Callback;
* Author M M Arif * 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 final Context context;
private Context mCtx; 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) { public ExploreRepositoriesAdapter(List<UserRepositories> dataList, Context ctx) {
this.context = ctx;
this.mCtx = mCtx; this.reposList = dataList;
this.searchedReposList = 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; @Override
private TextView repoName; public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
private TextView repoDescription; if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
private TextView fullName; 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 CheckBox isRepoAdmin;
private ImageView repoPrivatePublic; private final TextView repoStars;
private TextView repoStars; private final TextView repoLastUpdated;
private TextView repoForks; private final View spacerView;
private TextView repoOpenIssuesCount;
private TextView repoType;
private LinearLayout archiveRepo;
private TextView repoBranch;
private TextView htmlUrl;
private ReposSearchViewHolder(View itemView) {
RepositoriesHolder(View itemView) {
super(itemView); super(itemView);
repoName = itemView.findViewById(R.id.repoName); repoName = itemView.findViewById(R.id.repoName);
orgName = itemView.findViewById(R.id.orgName);
repoDescription = itemView.findViewById(R.id.repoDescription); repoDescription = itemView.findViewById(R.id.repoDescription);
image = itemView.findViewById(R.id.imageAvatar);
fullName = itemView.findViewById(R.id.repoFullName);
isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin); isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin);
repoPrivatePublic = itemView.findViewById(R.id.imageRepoType); image = itemView.findViewById(R.id.imageAvatar);
repoStars = itemView.findViewById(R.id.repoStars); repoStars = itemView.findViewById(R.id.repoStars);
repoForks = itemView.findViewById(R.id.repoForks); repoLastUpdated = itemView.findViewById(R.id.repoLastUpdated);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount); spacerView = itemView.findViewById(R.id.spacerView);
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);
itemView.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
Context context = v.getContext(); Context context = v.getContext();
TextView repoFullName = v.findViewById(R.id.repoFullName);
Intent intent = new Intent(context, RepoDetailActivity.class); Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", repoFullName.getText().toString()); intent.putExtra("repoFullName", userRepositories.getFullName());
TinyDB tinyDb = TinyDB.getInstance(context); tinyDb.putString("repoFullName", userRepositories.getFullName());
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putBoolean("resumeIssues", true); tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked()); 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 repoOwner = parts[0];
final String repoName = parts[1]; final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId"); int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context); RepositoriesApi repositoryData = BaseApi.getInstance(context, RepositoriesApi.class);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId); //RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
assert repositoryData != null;
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName); Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) { if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName); long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id); tinyDb.putLong("repositoryId", id);
} }
else { else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName); Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId()); tinyDb.putLong("repositoryId", data.getRepositoryId());
} }
//store if user is watching this repo //store if user is watching this repo
@ -131,195 +164,138 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token"); final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchInfo watch = new WatchInfo(); WatchInfo watch = new WatchInfo();
Call<WatchInfo> call; Call<WatchInfo> call;
call = RetrofitClient.getApiInterface(context).checkRepoWatchStatus(token, repoOwner, repoName); call = RetrofitClient.getApiInterface(context).checkRepoWatchStatus(token, repoOwner, repoName);
call.enqueue(new Callback<WatchInfo>() { call.enqueue(new Callback<WatchInfo>() {
@Override @Override
public void onResponse(@NonNull Call<WatchInfo> call, @NonNull retrofit2.Response<WatchInfo> response) { public void onResponse(@NonNull Call<WatchInfo> call, @NonNull retrofit2.Response<WatchInfo> response) {
if(response.isSuccessful()) { if(response.isSuccessful()) {
assert response.body() != null; assert response.body() != null;
tinyDb.putBoolean("repoWatch", response.body().getSubscribed()); tinyDb.putBoolean("repoWatch", response.body().getSubscribed());
}
} else { else {
tinyDb.putBoolean("repoWatch", false); tinyDb.putBoolean("repoWatch", false);
if(response.code() != 404) { if(response.code() != 404) {
Toasty.error(context, context.getString(R.string.genericApiStatusError)); Toasty.error(context, context.getString(R.string.genericApiStatusError));
} }
} }
} }
@Override @Override
public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) {
tinyDb.putBoolean("repoWatch", false); tinyDb.putBoolean("repoWatch", false);
Toasty.error(context, context.getString(R.string.genericApiStatusError)); Toasty.error(context, context.getString(R.string.genericApiStatusError));
} }
}); });
} }
context.startActivity(intent); 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 int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
@Override Locale locale = context.getResources().getConfiguration().locale;
public ExploreRepositoriesAdapter.ReposSearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { String timeFormat = tinyDb.getString("dateFormat");
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_repositories, parent, false); orgName.setText(userRepositories.getFullName().split("/")[0]);
return new ExploreRepositoriesAdapter.ReposSearchViewHolder(v); repoName.setText(userRepositories.getFullName().split("/")[1]);
} repoStars.setText(userRepositories.getStars_count());
@Override
public void onBindViewHolder(@NonNull final ExploreRepositoriesAdapter.ReposSearchViewHolder holder, int position) {
UserRepositories currentItem = searchedReposList.get(position);
holder.repoDescription.setVisibility(View.GONE);
holder.repoBranch.setText(currentItem.getDefault_branch());
holder.htmlUrl.setText(currentItem.getHtml_url());
ColorGenerator generator = ColorGenerator.MATERIAL; ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName()); int color = generator.getColor(userRepositories.getName());
String firstCharacter = String.valueOf(currentItem.getName().charAt(0)); String firstCharacter = String.valueOf(userRepositories.getFullName().charAt(0));
TextDrawable drawable = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT).fontSize(18).toUpperCase().width(28).height(28).endConfig().buildRoundRect(firstCharacter, color, 3); 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(userRepositories.getAvatar_url() != null) {
if(!currentItem.getAvatar_url().equals("")) { if(!userRepositories.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); 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 { else {
holder.image.setImageDrawable(drawable); image.setImageDrawable(drawable);
} }
} }
else { else {
holder.image.setImageDrawable(drawable); image.setImageDrawable(drawable);
} }
holder.repoName.setText(currentItem.getName()); if(userRepositories.getUpdated_at() != null) {
if(!currentItem.getDescription().equals("")) {
holder.repoDescription.setVisibility(View.VISIBLE); switch(timeFormat) {
holder.repoDescription.setText(currentItem.getDescription()); 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;
}
} }
holder.fullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
} }
else { else {
holder.repoPrivatePublic.setVisibility(View.GONE); repoLastUpdated.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(currentItem.isArchived()) { if(!userRepositories.getDescription().equals("")) {
holder.archiveRepo.setVisibility(View.VISIBLE); repoDescription.setVisibility(View.VISIBLE);
repoDescription.setText(userRepositories.getDescription());
spacerView.setVisibility(View.GONE);
} }
else { else {
holder.archiveRepo.setVisibility(View.GONE); repoDescription.setVisibility(View.GONE);
spacerView.setVisibility(View.VISIBLE);
} }
if(isRepoAdmin == null) {
isRepoAdmin = new CheckBox(context);
}
isRepoAdmin.setChecked(userRepositories.getPermissions().isAdmin());
}
} }
@Override static class LoadHolder extends RecyclerView.ViewHolder {
public int getItemCount() { LoadHolder(View itemView) {
super(itemView);
return searchedReposList.size(); }
} }
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() { public void notifyDataChanged() {
notifyDataSetChanged(); 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.Filter;
import android.widget.Filterable; import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.gitnex.tea4j.models.Files;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Files;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -23,55 +24,39 @@ import java.util.List;
public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHolder> implements Filterable { public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHolder> implements Filterable {
private List<Files> filesList; private final List<Files> originalFiles = new ArrayList<>();
private Context mCtx; private final List<Files> alteredFiles = new ArrayList<>();
private List<Files> filesListFull;
private FilesAdapterListener filesListener; private final Context context;
private final FilesAdapterListener filesListener;
public interface FilesAdapterListener { 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 Files file;
private ImageView dirTypeImage;
private ImageView unknownTypeImage; private final ImageView fileTypeIs;
private TextView fileName; private final TextView fileName;
private TextView fileType; private final TextView fileInfo;
private TextView fileInfo;
private FilesViewHolder(View itemView) { private FilesViewHolder(View itemView) {
super(itemView); super(itemView);
LinearLayout fileFrame = itemView.findViewById(R.id.fileFrame);
fileName = itemView.findViewById(R.id.fileName); fileName = itemView.findViewById(R.id.fileName);
fileTypeImage = itemView.findViewById(R.id.fileImage); fileTypeIs = itemView.findViewById(R.id.fileTypeIs);
dirTypeImage = itemView.findViewById(R.id.dirImage);
unknownTypeImage = itemView.findViewById(R.id.unknownImage);
fileType = itemView.findViewById(R.id.fileType);
fileInfo = itemView.findViewById(R.id.fileInfo); fileInfo = itemView.findViewById(R.id.fileInfo);
fileFrame.setOnClickListener(v -> filesListener.onClickFile(file));
//ImageView filesDropdownMenu = itemView.findViewById(R.id.filesDropdownMenu); //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() { /*filesDropdownMenu.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { 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) { public FilesAdapter(Context ctx, FilesAdapterListener filesListener) {
this.mCtx = mCtx;
this.filesList = filesListMain; this.context = ctx;
filesListFull = new ArrayList<>(filesList);
this.filesListener = filesListener; this.filesListener = filesListener;
} }
public List<Files> getOriginalFiles() {
return originalFiles;
}
public void notifyOriginalDataSetChanged() {
alteredFiles.clear();
alteredFiles.addAll(originalFiles);
notifyDataSetChanged();
}
@NonNull @NonNull
@Override @Override
public FilesAdapter.FilesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public FilesAdapter.FilesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@ -155,35 +151,43 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
@Override @Override
public void onBindViewHolder(@NonNull FilesAdapter.FilesViewHolder holder, int position) { 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()); holder.fileName.setText(currentItem.getName());
if(currentItem.getType().equals("file")) { switch(currentItem.getType()) {
holder.fileTypeImage.setVisibility(View.VISIBLE);
holder.dirTypeImage.setVisibility(View.GONE); case "file":
holder.unknownTypeImage.setVisibility(View.GONE); holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.ic_file));
holder.fileInfo.setVisibility(View.VISIBLE); holder.fileInfo.setVisibility(View.VISIBLE);
holder.fileInfo.setText(FileUtils.byteCountToDisplaySize(currentItem.getSize())); holder.fileInfo.setText(FileUtils.byteCountToDisplaySize(currentItem.getSize()));
} break;
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);
}
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 @Override
public int getItemCount() { public int getItemCount() {
return filesList.size(); return alteredFiles.size();
} }
@Override @Override
@ -191,17 +195,19 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
return filesFilter; return filesFilter;
} }
private Filter filesFilter = new Filter() { private final Filter filesFilter = new Filter() {
@Override @Override
protected FilterResults performFiltering(CharSequence constraint) { protected FilterResults performFiltering(CharSequence constraint) {
List<Files> filteredList = new ArrayList<>(); List<Files> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) { if (constraint == null || constraint.length() == 0) {
filteredList.addAll(filesListFull); filteredList.addAll(originalFiles);
} else { } else {
String filterPattern = constraint.toString().toLowerCase().trim(); 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)) { if (item.getName().toLowerCase().contains(filterPattern) || item.getPath().toLowerCase().contains(filterPattern)) {
filteredList.add(item); filteredList.add(item);
} }
@ -212,14 +218,19 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
results.values = filteredList; results.values = filteredList;
return results; return results;
} }
@Override @Override
protected void publishResults(CharSequence constraint, FilterResults results) { protected void publishResults(CharSequence constraint, FilterResults results) {
filesList.clear();
filesList.addAll((List) results.values); alteredFiles.clear();
alteredFiles.addAll((List) results.values);
notifyDataSetChanged(); notifyDataSetChanged();
} }
}; };
} }

View File

@ -13,10 +13,10 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import org.gitnex.tea4j.models.FileDiffView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.fragments.BottomSheetReplyFragment; import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.models.FileDiffView;
import org.mian.gitnex.views.DiffTextView; import org.mian.gitnex.views.DiffTextView;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -54,7 +54,6 @@ public class FilesDiffAdapter extends BaseAdapter {
COLOR_NORMAL = AppUtil.getColorFromAttribute(context, R.attr.primaryBackgroundColor); COLOR_NORMAL = AppUtil.getColorFromAttribute(context, R.attr.primaryBackgroundColor);
COLOR_SELECTED = AppUtil.getColorFromAttribute(context, R.attr.diffSelectedColor); COLOR_SELECTED = AppUtil.getColorFromAttribute(context, R.attr.diffSelectedColor);
COLOR_FONT = AppUtil.getColorFromAttribute(context, R.attr.inputTextColor); COLOR_FONT = AppUtil.getColorFromAttribute(context, R.attr.inputTextColor);
} }
@Override @Override
@ -94,7 +93,6 @@ public class FilesDiffAdapter extends BaseAdapter {
diffStats.setVisibility(View.GONE); diffStats.setVisibility(View.GONE);
diffLines.addView(getMessageView(context.getResources().getString(R.string.binaryFileError))); diffLines.addView(getMessageView(context.getResources().getString(R.string.binaryFileError)));
} }
else { else {
@ -168,7 +166,6 @@ public class FilesDiffAdapter extends BaseAdapter {
} }
diffTextView.setOnClickListener(v -> { diffTextView.setOnClickListener(v -> {
if(((DiffTextView) v).getCurrentBackgroundColor() != COLOR_SELECTED) { if(((DiffTextView) v).getCurrentBackgroundColor() != COLOR_SELECTED) {
@ -197,7 +194,6 @@ public class FilesDiffAdapter extends BaseAdapter {
stringBuilder.append(((DiffTextView) view).getText()); stringBuilder.append(((DiffTextView) view).getText());
stringBuilder.append("\n"); stringBuilder.append("\n");
} }
stringBuilder.append("```\n\n"); stringBuilder.append("```\n\n");
@ -209,7 +205,6 @@ public class FilesDiffAdapter extends BaseAdapter {
bundle.putBoolean("cursorToEnd", true); bundle.putBoolean("cursorToEnd", true);
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet"); BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
} }
return true; return true;
@ -226,7 +221,6 @@ public class FilesDiffAdapter extends BaseAdapter {
else { else {
diffLines.addView(getMessageView(context.getResources().getString(R.string.fileTooLarge))); diffLines.addView(getMessageView(context.getResources().getString(R.string.fileTooLarge)));
} }
} }
@ -248,13 +242,11 @@ public class FilesDiffAdapter extends BaseAdapter {
textView.setText(message); textView.setText(message);
return textView; return textView;
} }
private String[] getLines(String content) { private String[] getLines(String content) {
return content.split("\\R"); return content.split("\\R");
} }
} }

View File

@ -6,6 +6,8 @@ import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -18,7 +20,9 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog; import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.vdurmont.emoji.EmojiParser; import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.IssueComments;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BottomSheetReplyFragment; import org.mian.gitnex.fragments.BottomSheetReplyFragment;
@ -29,7 +33,6 @@ import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper; import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.IssueComments;
import org.mian.gitnex.views.ReactionList; import org.mian.gitnex.views.ReactionList;
import org.mian.gitnex.views.ReactionSpinner; import org.mian.gitnex.views.ReactionSpinner;
import java.util.List; import java.util.List;
@ -44,27 +47,28 @@ import retrofit2.Callback;
public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdapter.IssueCommentViewHolder> { public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdapter.IssueCommentViewHolder> {
private final Context ctx; private final Context context;
private final TinyDB tinyDB; private final TinyDB tinyDB;
private final Bundle bundle; private final Bundle bundle;
private final List<IssueComments> issuesComments; private final List<IssueComments> issuesComments;
private final FragmentManager fragmentManager; private final FragmentManager fragmentManager;
private final BottomSheetReplyFragment.OnInteractedListener onInteractedListener; private final BottomSheetReplyFragment.OnInteractedListener onInteractedListener;
private final Locale locale;
public IssueCommentsAdapter(Context ctx, Bundle bundle, List<IssueComments> issuesCommentsMain, FragmentManager fragmentManager, BottomSheetReplyFragment.OnInteractedListener onInteractedListener) { public IssueCommentsAdapter(Context ctx, Bundle bundle, List<IssueComments> issuesCommentsMain, FragmentManager fragmentManager, BottomSheetReplyFragment.OnInteractedListener onInteractedListener) {
this.ctx = ctx; this.context = ctx;
this.bundle = bundle; this.bundle = bundle;
this.issuesComments = issuesCommentsMain; this.issuesComments = issuesCommentsMain;
this.fragmentManager = fragmentManager; this.fragmentManager = fragmentManager;
this.onInteractedListener = onInteractedListener; this.onInteractedListener = onInteractedListener;
tinyDB = TinyDB.getInstance(ctx); tinyDB = TinyDB.getInstance(ctx);
locale = ctx.getResources().getConfiguration().locale;
} }
class IssueCommentViewHolder extends RecyclerView.ViewHolder { class IssueCommentViewHolder extends RecyclerView.ViewHolder {
private String userLoginId;
private IssueComments issueComment; private IssueComments issueComment;
private final ImageView avatar; private final ImageView avatar;
@ -86,10 +90,9 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
menu.setOnClickListener(v -> { menu.setOnClickListener(v -> {
final Context ctx = v.getContext();
final String loginUid = tinyDB.getString("loginUid"); final String loginUid = tinyDB.getString("loginUid");
@SuppressLint("InflateParams") View vw = LayoutInflater.from(ctx).inflate(R.layout.bottom_sheet_issue_comments, null); @SuppressLint("InflateParams") View vw = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_issue_comments, null);
TextView commentMenuEdit = vw.findViewById(R.id.commentMenuEdit); TextView commentMenuEdit = vw.findViewById(R.id.commentMenuEdit);
TextView commentShare = vw.findViewById(R.id.issueCommentShare); TextView commentShare = vw.findViewById(R.id.issueCommentShare);
@ -107,30 +110,37 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
commentMenuCopy.setVisibility(View.GONE); commentMenuCopy.setVisibility(View.GONE);
} }
BottomSheetDialog dialog = new BottomSheetDialog(ctx); BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(vw); dialog.setContentView(vw);
dialog.show(); dialog.show();
LinearLayout linearLayout = vw.findViewById(R.id.commentReactionButtons); 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 bundle1 = new Bundle(); Bundle bundle1 = new Bundle();
bundle1.putAll(bundle); bundle1.putAll(bundle);
bundle1.putInt("commentId", issueComment.getId()); bundle1.putInt("commentId", issueComment.getId());
ReactionSpinner reactionSpinner = new ReactionSpinner(ctx, bundle1); ReactionSpinner reactionSpinner = new ReactionSpinner(context, bundle1);
reactionSpinner.setOnInteractedListener(() -> { reactionSpinner.setOnInteractedListener(() -> {
tinyDB.putBoolean("commentEdited", true); tinyDB.putBoolean("commentEdited", true);
onInteractedListener.onInteracted(); onInteractedListener.onInteracted();
dialog.dismiss(); dialog.dismiss();
}); });
Handler handler = new Handler();
handler.postDelayed(() -> {
linearLayout.removeView(loadReactions);
reactionSpinner.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 160));
linearLayout.addView(reactionSpinner); linearLayout.addView(reactionSpinner);
}, 2500);
commentMenuEdit.setOnClickListener(v1 -> { commentMenuEdit.setOnClickListener(v1 -> {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putInt("commentId", issueComment.getId()); bundle.putInt("commentId", issueComment.getId());
bundle.putString("commentAction", "edit"); bundle.putString("commentAction", "edit");
@ -141,56 +151,48 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
bottomSheetReplyFragment.show(fragmentManager, "replyBottomSheet"); bottomSheetReplyFragment.show(fragmentManager, "replyBottomSheet");
dialog.dismiss(); dialog.dismiss();
}); });
commentShare.setOnClickListener(v1 -> { commentShare.setOnClickListener(v1 -> {
// get comment Url // get comment Url
CharSequence commentUrl = issueComment.getHtml_url(); CharSequence commentUrl = issueComment.getHtml_url();
// share issue comment // share issue comment
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain"); sharingIntent.setType("text/plain");
String intentHeader = tinyDB.getString("issueNumber") + ctx.getResources().getString(R.string.hash) + "issuecomment-" + issueComment.getId() + " " + 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_SUBJECT, intentHeader);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, commentUrl); sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, commentUrl);
ctx.startActivity(Intent.createChooser(sharingIntent, intentHeader)); context.startActivity(Intent.createChooser(sharingIntent, intentHeader));
dialog.dismiss(); dialog.dismiss();
}); });
issueCommentCopyUrl.setOnClickListener(v1 -> { issueCommentCopyUrl.setOnClickListener(v1 -> {
// comment Url // comment Url
CharSequence commentUrl = issueComment.getHtml_url(); 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; assert clipboard != null;
ClipData clip = ClipData.newPlainText(commentUrl, commentUrl); ClipData clip = ClipData.newPlainText(commentUrl, commentUrl);
clipboard.setPrimaryClip(clip); clipboard.setPrimaryClip(clip);
dialog.dismiss(); dialog.dismiss();
Toasty.success(ctx, ctx.getString(R.string.copyIssueUrlToastMsg)); Toasty.success(context, context.getString(R.string.copyIssueUrlToastMsg));
}); });
commentMenuQuote.setOnClickListener(v1 -> { commentMenuQuote.setOnClickListener(v1 -> {
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
String commenterName = issueComment.getUser().getUsername(); String commenterName = issueComment.getUser().getUsername();
if(!commenterName.equals(tinyDB.getString("userLogin"))) { if(!commenterName.equals(tinyDB.getString("userLogin"))) {
stringBuilder.append("@").append(commenterName).append("\n\n"); stringBuilder.append("@").append(commenterName).append("\n\n");
} }
String[] lines = issueComment.getBody().split("\\R"); String[] lines = issueComment.getBody().split("\\R");
for(String line : lines) { for(String line : lines) {
stringBuilder.append(">").append(line).append("\n"); stringBuilder.append(">").append(line).append("\n");
} }
@ -202,33 +204,37 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
dialog.dismiss(); dialog.dismiss();
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet"); BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
}); });
commentMenuCopy.setOnClickListener(v1 -> { commentMenuCopy.setOnClickListener(v1 -> {
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(context).getSystemService(Context.CLIPBOARD_SERVICE);
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
assert clipboard != null; assert clipboard != null;
ClipData clip = ClipData.newPlainText("Comment on issue #" + tinyDB.getString("issueNumber"), issueComment.getBody()); ClipData clip = ClipData.newPlainText("Comment on issue #" + tinyDB.getString("issueNumber"), issueComment.getBody());
clipboard.setPrimaryClip(clip); clipboard.setPrimaryClip(clip);
dialog.dismiss(); dialog.dismiss();
Toasty.success(ctx, ctx.getString(R.string.copyIssueCommentToastMsg)); Toasty.success(context, context.getString(R.string.copyIssueCommentToastMsg));
}); });
commentMenuDelete.setOnClickListener(v1 -> { commentMenuDelete.setOnClickListener(v1 -> {
deleteIssueComment(context, issueComment.getId(), getAdapterPosition());
deleteIssueComment(ctx, issueComment.getId(), getAdapterPosition());
dialog.dismiss(); 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) { private void updateAdapter(int position) {
@ -236,7 +242,6 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
issuesComments.remove(position); issuesComments.remove(position);
notifyItemRemoved(position); notifyItemRemoved(position);
notifyItemRangeChanged(position, issuesComments.size()); notifyItemRangeChanged(position, issuesComments.size());
} }
private void deleteIssueComment(final Context ctx, final int commentId, int position) { private void deleteIssueComment(final Context ctx, final int commentId, int position) {
@ -303,46 +308,43 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_issue_comments, parent, false); View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_issue_comments, parent, false);
return new IssueCommentsAdapter.IssueCommentViewHolder(v); return new IssueCommentsAdapter.IssueCommentViewHolder(v);
} }
@Override @Override
public void onBindViewHolder(@NonNull IssueCommentsAdapter.IssueCommentViewHolder holder, int position) { public void onBindViewHolder(@NonNull IssueCommentsAdapter.IssueCommentViewHolder holder, int position) {
String timeFormat = tinyDB.getString("dateFormat"); String timeFormat = tinyDB.getString("dateFormat");
IssueComments issueComment = issuesComments.get(position); IssueComments issueComment = issuesComments.get(position);
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
holder.userLoginId = issueComment.getUser().getLogin();
holder.issueComment = issueComment; holder.issueComment = issueComment;
holder.author.setText(issueComment.getUser().getUsername()); holder.author.setText(issueComment.getUser().getUsername());
PicassoService.getInstance(ctx).get() PicassoService.getInstance(context).get()
.load(issueComment.getUser().getAvatar_url()) .load(issueComment.getUser().getAvatar_url())
.placeholder(R.drawable.loader_animated) .placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(4, 0)) .transform(new RoundedTransformation(imgRadius, 0))
.resize(AppUtil.getPixelsFromDensity(ctx, 35), AppUtil.getPixelsFromDensity(ctx, 35)) .resize(AppUtil.getPixelsFromDensity(context, 35), AppUtil.getPixelsFromDensity(context, 35))
.centerCrop() .centerCrop()
.into(holder.avatar); .into(holder.avatar);
new Markdown(ctx, EmojiParser.parseToUnicode(issueComment.getBody()), holder.comment); Markdown.render(context, EmojiParser.parseToUnicode(issueComment.getBody()), holder.comment);
StringBuilder informationBuilder = null; StringBuilder informationBuilder = null;
if(issueComment.getCreated_at() != null) { if(issueComment.getCreated_at() != null) {
if(timeFormat.equals("pretty")) { if(timeFormat.equals("pretty")) {
informationBuilder = new StringBuilder(TimeHelper.formatTime(issueComment.getCreated_at(), locale, "pretty", context));
informationBuilder = new StringBuilder(TimeHelper.formatTime(issueComment.getCreated_at(), Locale.getDefault(), "pretty", ctx));
holder.information.setOnClickListener(v -> TimeHelper.customDateFormatForToastDateFormat(issueComment.getCreated_at())); holder.information.setOnClickListener(v -> TimeHelper.customDateFormatForToastDateFormat(issueComment.getCreated_at()));
} }
else if(timeFormat.equals("normal")) { else if(timeFormat.equals("normal")) {
informationBuilder = new StringBuilder(TimeHelper.formatTime(issueComment.getCreated_at(), locale, "normal", context));
informationBuilder = new StringBuilder(TimeHelper.formatTime(issueComment.getCreated_at(), Locale.getDefault(), "normal", ctx));
} }
if(!issueComment.getCreated_at().equals(issueComment.getUpdated_at())) { if(!issueComment.getCreated_at().equals(issueComment.getUpdated_at())) {
if(informationBuilder != null) { if(informationBuilder != null) {
informationBuilder.append(context.getString(R.string.colorfulBulletSpan)).append(context.getString(R.string.modifiedText));
informationBuilder.append(ctx.getString(R.string.colorfulBulletSpan)).append(ctx.getString(R.string.modifiedText));
} }
} }
} }
@ -353,7 +355,7 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
bundle1.putAll(bundle); bundle1.putAll(bundle);
bundle1.putInt("commentId", issueComment.getId()); bundle1.putInt("commentId", issueComment.getId());
ReactionList reactionList = new ReactionList(ctx, bundle1); ReactionList reactionList = new ReactionList(context, bundle1);
holder.commentReactionBadges.addView(reactionList); holder.commentReactionBadges.addView(reactionList);
reactionList.setOnReactionAddedListener(() -> { reactionList.setOnReactionAddedListener(() -> {
@ -367,7 +369,6 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
@Override @Override
public int getItemCount() { public int getItemCount() {
return issuesComments.size(); return issuesComments.size();
} }

View File

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

View File

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

View File

@ -9,8 +9,8 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.Labels;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.models.Labels;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
@ -22,11 +22,11 @@ import java.util.List;
public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.LabelsViewHolder> { public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.LabelsViewHolder> {
private List<Integer> currentLabelsIds; private List<Integer> currentLabelsIds;
private List<Labels> labels; private final List<Labels> labels;
private List<String> labelsStrings = new ArrayList<>(); private final List<String> labelsStrings = new ArrayList<>();
private List<Integer> labelsIds = new ArrayList<>(); private List<Integer> labelsIds = new ArrayList<>();
private LabelsListAdapterListener labelsListener; private final LabelsListAdapterListener labelsListener;
public interface LabelsListAdapterListener { public interface LabelsListAdapterListener {
@ -43,9 +43,9 @@ public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.La
static class LabelsViewHolder extends RecyclerView.ViewHolder { static class LabelsViewHolder extends RecyclerView.ViewHolder {
private CheckBox labelSelection; private final CheckBox labelSelection;
private TextView labelText; private final TextView labelText;
private ImageView labelColor; private final ImageView labelColor;
private LabelsViewHolder(View itemView) { private LabelsViewHolder(View itemView) {

View File

@ -2,6 +2,8 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -10,10 +12,12 @@ import android.widget.Filter;
import android.widget.Filterable; import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import org.gitnex.tea4j.models.UserInfo;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -23,26 +27,40 @@ import java.util.List;
public class MembersByOrgAdapter extends BaseAdapter implements Filterable { public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
private List<UserInfo> membersList; private final List<UserInfo> membersList;
private Context mCtx; private final Context context;
private List<UserInfo> membersListFull; private final List<UserInfo> membersListFull;
private class ViewHolder { private class ViewHolder {
private ImageView memberAvatar; private String userLoginId;
private TextView memberName;
private final ImageView memberAvatar;
private final TextView memberName;
ViewHolder(View v) { ViewHolder(View v) {
memberAvatar = v.findViewById(R.id.memberAvatar); memberAvatar = v.findViewById(R.id.memberAvatar);
memberName = v.findViewById(R.id.memberName); 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) { public MembersByOrgAdapter(Context ctx, List<UserInfo> membersListMain) {
this.mCtx = mCtx;
this.context = ctx;
this.membersList = membersListMain; this.membersList = membersListMain;
membersListFull = new ArrayList<>(membersList); membersListFull = new ArrayList<>(membersList);
} }
@Override @Override
@ -67,31 +85,37 @@ public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
MembersByOrgAdapter.ViewHolder viewHolder = null; MembersByOrgAdapter.ViewHolder viewHolder = null;
if (finalView == 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); finalView.setTag(viewHolder);
} }
else { else {
viewHolder = (MembersByOrgAdapter.ViewHolder) finalView.getTag(); viewHolder = (MembersByOrgAdapter.ViewHolder) finalView.getTag();
} }
initData(viewHolder, position); initData(viewHolder, position);
return finalView; return finalView;
} }
private void initData(MembersByOrgAdapter.ViewHolder viewHolder, int position) { private void initData(MembersByOrgAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = membersList.get(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("")) { if(!currentItem.getFullname().equals("")) {
viewHolder.memberName.setText(currentItem.getFullname());
viewHolder.memberName.setText(Html.fromHtml(currentItem.getFullname()));
} }
else { else {
viewHolder.memberName.setText(currentItem.getLogin()); viewHolder.memberName.setText(currentItem.getLogin());
} }
} }
@Override @Override
@ -99,14 +123,17 @@ public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
return membersFilter; return membersFilter;
} }
private Filter membersFilter = new Filter() { private final Filter membersFilter = new Filter() {
@Override @Override
protected FilterResults performFiltering(CharSequence constraint) { protected FilterResults performFiltering(CharSequence constraint) {
List<UserInfo> filteredList = new ArrayList<>(); List<UserInfo> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) { if (constraint == null || constraint.length() == 0) {
filteredList.addAll(membersListFull); filteredList.addAll(membersListFull);
} else { }
else {
String filterPattern = constraint.toString().toLowerCase().trim(); String filterPattern = constraint.toString().toLowerCase().trim();
for (UserInfo item : membersListFull) { for (UserInfo item : membersListFull) {
@ -124,6 +151,7 @@ public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
@Override @Override
protected void publishResults(CharSequence constraint, FilterResults results) { protected void publishResults(CharSequence constraint, FilterResults results) {
membersList.clear(); membersList.clear();
membersList.addAll((List) results.values); membersList.addAll((List) results.values);
notifyDataSetChanged(); notifyDataSetChanged();

View File

@ -10,17 +10,18 @@ import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog; import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.vdurmont.emoji.EmojiParser; import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.Milestones;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.actions.MilestoneActions; import org.mian.gitnex.actions.MilestoneActions;
import org.mian.gitnex.helpers.ClickListener; import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Markdown; import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TimeHelper; import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Milestones;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -34,19 +35,17 @@ import java.util.Locale;
public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context; private final Context context;
private final int TYPE_LOAD = 0; private final int TYPE_LOAD = 0;
private List<Milestones> dataList; private List<Milestones> dataList;
private OnLoadMoreListener loadMoreListener; private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false; private boolean isLoading = false;
private boolean isMoreDataAvailable = true; 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; this.dataList = dataListMain;
} }
@NonNull @NonNull
@ -61,7 +60,6 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
else { else {
return new MilestonesAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false)); return new MilestonesAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
} }
} }
@Override @Override
@ -71,33 +69,29 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
isLoading = true; isLoading = true;
loadMoreListener.onLoadMore(); loadMoreListener.onLoadMore();
} }
if(getItemViewType(position) == TYPE_LOAD) { if(getItemViewType(position) == TYPE_LOAD) {
((MilestonesAdapter.DataHolder) holder).bindData(dataList.get(position)); ((MilestonesAdapter.DataHolder) holder).bindData(dataList.get(position));
} }
} }
class DataHolder extends RecyclerView.ViewHolder { class DataHolder extends RecyclerView.ViewHolder {
private TextView milestoneId; private Milestones milestones;
private TextView msTitle;
private TextView msDescription; private final TextView msTitle;
private TextView msOpenIssues; private final TextView msDescription;
private TextView msClosedIssues; private final TextView msOpenIssues;
private TextView msDueDate; private final TextView msClosedIssues;
private ProgressBar msProgress; private final TextView msDueDate;
private TextView milestoneStatus; private final ProgressBar msProgress;
DataHolder(View itemView) { DataHolder(View itemView) {
super(itemView); super(itemView);
milestoneId = itemView.findViewById(R.id.milestoneId);
msTitle = itemView.findViewById(R.id.milestoneTitle); msTitle = itemView.findViewById(R.id.milestoneTitle);
msDescription = itemView.findViewById(R.id.milestoneDescription); msDescription = itemView.findViewById(R.id.milestoneDescription);
msOpenIssues = itemView.findViewById(R.id.milestoneIssuesOpen); msOpenIssues = itemView.findViewById(R.id.milestoneIssuesOpen);
@ -105,12 +99,11 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
msDueDate = itemView.findViewById(R.id.milestoneDueDate); msDueDate = itemView.findViewById(R.id.milestoneDueDate);
msProgress = itemView.findViewById(R.id.milestoneProgress); msProgress = itemView.findViewById(R.id.milestoneProgress);
ImageView milestonesMenu = itemView.findViewById(R.id.milestonesMenu); ImageView milestonesMenu = itemView.findViewById(R.id.milestonesMenu);
milestoneStatus = itemView.findViewById(R.id.milestoneStatus);
milestonesMenu.setOnClickListener(v -> { milestonesMenu.setOnClickListener(v -> {
Context ctx = v.getContext(); 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); @SuppressLint("InflateParams") View view = LayoutInflater.from(ctx).inflate(R.layout.bottom_sheet_milestones_in_list, null);
@ -121,17 +114,15 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
dialog.setContentView(view); dialog.setContentView(view);
dialog.show(); dialog.show();
if(milestoneStatus.getText().toString().equals("open")) { if(milestones.getState().equals("open")) {
closeMilestone.setVisibility(View.VISIBLE); closeMilestone.setVisibility(View.VISIBLE);
openMilestone.setVisibility(View.GONE); openMilestone.setVisibility(View.GONE);
} }
else { else {
closeMilestone.setVisibility(View.GONE); closeMilestone.setVisibility(View.GONE);
openMilestone.setVisibility(View.VISIBLE); openMilestone.setVisibility(View.VISIBLE);
} }
closeMilestone.setOnClickListener(v12 -> { closeMilestone.setOnClickListener(v12 -> {
@ -139,7 +130,6 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
MilestoneActions.closeMilestone(ctx, milestoneId_); MilestoneActions.closeMilestone(ctx, milestoneId_);
dialog.dismiss(); dialog.dismiss();
updateAdapter(getAdapterPosition()); updateAdapter(getAdapterPosition());
}); });
openMilestone.setOnClickListener(v12 -> { openMilestone.setOnClickListener(v12 -> {
@ -147,7 +137,6 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
MilestoneActions.openMilestone(ctx, milestoneId_); MilestoneActions.openMilestone(ctx, milestoneId_);
dialog.dismiss(); dialog.dismiss();
updateAdapter(getAdapterPosition()); updateAdapter(getAdapterPosition());
}); });
}); });
@ -157,18 +146,16 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
void bindData(Milestones dataModel) { void bindData(Milestones dataModel) {
this.milestones = dataModel;
final TinyDB tinyDb = TinyDB.getInstance(context); final TinyDB tinyDb = TinyDB.getInstance(context);
final String locale = tinyDb.getString("locale"); final String locale = context.getResources().getConfiguration().locale.getLanguage();
final String timeFormat = tinyDb.getString("dateFormat"); final String timeFormat = tinyDb.getString("dateFormat");
milestoneId.setText(String.valueOf(dataModel.getId())); Markdown.render(context, dataModel.getTitle(), msTitle);
milestoneStatus.setText(dataModel.getState());
new Markdown(context, dataModel.getTitle(), msTitle);
if(!dataModel.getDescription().equals("")) { if(!dataModel.getDescription().equals("")) {
new Markdown(context, EmojiParser.parseToUnicode(dataModel.getDescription()), msDescription); Markdown.render(context, EmojiParser.parseToUnicode(dataModel.getDescription()), msDescription);
} }
else { else {
@ -184,14 +171,12 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
msProgress.setProgress(100); msProgress.setProgress(100);
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 100), context)); msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 100), context));
} }
else { else {
int msCompletion = 100 * dataModel.getClosed_issues() / (dataModel.getOpen_issues() + dataModel.getClosed_issues()); 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.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, msCompletion), context));
msProgress.setProgress(msCompletion); msProgress.setProgress(msCompletion);
} }
} }
@ -199,11 +184,11 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
msProgress.setProgress(0); msProgress.setProgress(0);
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 0), context)); msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 0), context));
} }
if(dataModel.getDue_on() != null) { if(dataModel.getDue_on() != null) {
String TAG = Constants.tagMilestonesAdapter;
if(timeFormat.equals("normal") || timeFormat.equals("pretty")) { if(timeFormat.equals("normal") || timeFormat.equals("pretty")) {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", new Locale(locale)); DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", new Locale(locale));
@ -220,12 +205,11 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
String dueDate = formatter.format(date); String dueDate = formatter.format(date);
if(date.before(new 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.setText(dueDate);
msDueDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToast(dataModel.getDue_on()), context)); msDueDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToast(dataModel.getDue_on()), context));
} }
else if(timeFormat.equals("normal1")) { else if(timeFormat.equals("normal1")) {
@ -243,7 +227,6 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
assert date1 != null; assert date1 != null;
String dueDate = formatter.format(date1); String dueDate = formatter.format(date1);
msDueDate.setText(dueDate); msDueDate.setText(dueDate);
} }
} }
@ -261,7 +244,6 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
dataList.remove(position); dataList.remove(position);
notifyItemRemoved(position); notifyItemRemoved(position);
notifyItemRangeChanged(position, dataList.size()); notifyItemRangeChanged(position, dataList.size());
} }
@Override @Override
@ -273,14 +255,12 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
else { else {
return 1; return 1;
} }
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return dataList.size(); return dataList.size();
} }
static class LoadHolder extends RecyclerView.ViewHolder { static class LoadHolder extends RecyclerView.ViewHolder {
@ -289,32 +269,27 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
super(itemView); super(itemView);
} }
} }
public void setMoreDataAvailable(boolean moreDataAvailable) { public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable; isMoreDataAvailable = moreDataAvailable;
} }
public void notifyDataChanged() { public void notifyDataChanged() {
notifyDataSetChanged(); notifyDataSetChanged();
isLoading = false; isLoading = false;
} }
public interface OnLoadMoreListener { public interface OnLoadMoreListener {
void onLoadMore(); void onLoadMore();
} }
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) { public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener; this.loadMoreListener = loadMoreListener;
} }
public void updateList(List<Milestones> list) { public void updateList(List<Milestones> list) {

View File

@ -6,26 +6,27 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; 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.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.RecyclerView; 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 * 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 final List<Emails> emailsList;
private Context mCtx; private final Context context;
static class EmailsViewHolder extends RecyclerView.ViewHolder { static class EmailsViewHolder extends RecyclerView.ViewHolder {
private ImageView emailPrimary; private final ImageView emailPrimary;
private TextView userEmail; private final TextView userEmail;
private EmailsViewHolder(View itemView) { private EmailsViewHolder(View itemView) {
super(itemView); super(itemView);
@ -36,20 +37,20 @@ public class ProfileEmailsAdapter extends RecyclerView.Adapter<ProfileEmailsAdap
} }
} }
public ProfileEmailsAdapter(Context mCtx, List<Emails> emailsListMain) { public MyProfileEmailsAdapter(Context ctx, List<Emails> emailsListMain) {
this.mCtx = mCtx; this.context = ctx;
this.emailsList = emailsListMain; this.emailsList = emailsListMain;
} }
@NonNull @NonNull
@Override @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); 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 @Override
public void onBindViewHolder(@NonNull ProfileEmailsAdapter.EmailsViewHolder holder, int position) { public void onBindViewHolder(@NonNull MyProfileEmailsAdapter.EmailsViewHolder holder, int position) {
Emails currentItem = emailsList.get(position); Emails currentItem = emailsList.get(position);
@ -58,12 +59,12 @@ public class ProfileEmailsAdapter extends RecyclerView.Adapter<ProfileEmailsAdap
if(currentItem.getPrimary()) { if(currentItem.getPrimary()) {
TextDrawable drawable = TextDrawable.builder() TextDrawable drawable = TextDrawable.builder()
.beginConfig() .beginConfig()
.textColor(mCtx.getResources().getColor(R.color.colorWhite)) .textColor(ResourcesCompat.getColor(context.getResources(), R.color.colorWhite, null))
.fontSize(36) .fontSize(36)
.width(220) .width(220)
.height(60) .height(60)
.endConfig() .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); holder.emailPrimary.setImageDrawable(drawable);
} }
else { 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; package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Typeface; import android.graphics.Typeface;
@ -13,31 +10,32 @@ import android.widget.CheckBox;
import android.widget.Filter; import android.widget.Filter;
import android.widget.Filterable; import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator; 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.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity; 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.PicassoService;
import org.mian.gitnex.clients.RetrofitClient; 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.RepositoriesApi;
import org.mian.gitnex.database.models.Repository; 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.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories; import org.ocpsoft.prettytime.PrettyTime;
import org.mian.gitnex.models.WatchInfo; import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Locale;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -47,79 +45,75 @@ import retrofit2.Callback;
public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.MyReposViewHolder> implements Filterable { public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.MyReposViewHolder> implements Filterable {
private List<UserRepositories> reposList; private final List<UserRepositories> reposList;
private Context mCtx; private final Context context;
private List<UserRepositories> reposListFull; private final List<UserRepositories> reposListFull;
static class MyReposViewHolder extends RecyclerView.ViewHolder { static class MyReposViewHolder extends RecyclerView.ViewHolder {
private ImageView imageAvatar; private UserRepositories userRepositories;
private TextView repoName;
private TextView repoDescription; private final ImageView image;
private TextView repoFullName; private final TextView repoName;
private ImageView repoPrivatePublic; private final TextView orgName;
private TextView repoStars; private final TextView repoDescription;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private CheckBox isRepoAdmin; private CheckBox isRepoAdmin;
private LinearLayout archiveRepo; private final TextView repoStars;
private TextView repoBranch; private final TextView repoLastUpdated;
private TextView htmlUrl; private final View spacerView;
private MyReposViewHolder(View itemView) { private MyReposViewHolder(View itemView) {
super(itemView); super(itemView);
repoName = itemView.findViewById(R.id.repoName); repoName = itemView.findViewById(R.id.repoName);
orgName = itemView.findViewById(R.id.orgName);
repoDescription = itemView.findViewById(R.id.repoDescription); 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); isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame); image = itemView.findViewById(R.id.imageAvatar);
repoBranch = itemView.findViewById(R.id.repoBranch); repoStars = itemView.findViewById(R.id.repoStars);
htmlUrl = itemView.findViewById(R.id.htmlUrl); repoLastUpdated = itemView.findViewById(R.id.repoLastUpdated);
spacerView = itemView.findViewById(R.id.spacerView);
itemView.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
Context context = v.getContext(); Context context = v.getContext();
TinyDB tinyDb = TinyDB.getInstance(context);
Intent intent = new Intent(context, RepoDetailActivity.class); Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", repoFullName.getText().toString()); intent.putExtra("repoFullName", userRepositories.getFullName());
TinyDB tinyDb = TinyDB.getInstance(context); tinyDb.putString("repoFullName", userRepositories.getFullName());
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putString("repoType", repoType.getText().toString());
//tinyDb.putBoolean("resumeIssues", true); //tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked()); 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 repoOwner = parts[0];
final String repoName = parts[1]; final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId"); int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context); RepositoriesApi repositoryData = BaseApi.getInstance(context, RepositoriesApi.class);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId); //RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
assert repositoryData != null;
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName); Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) { if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName); long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id); tinyDb.putLong("repositoryId", id);
} }
else { else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName); Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId()); tinyDb.putLong("repositoryId", data.getRepositoryId());
} }
//store if user is watching this repo //store if user is watching this repo
@ -172,81 +166,13 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
context.startActivity(intent); 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; this.reposList = reposListMain;
reposListFull = new ArrayList<>(reposList); reposListFull = new ArrayList<>(reposList);
} }
@ -262,59 +188,77 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
@Override @Override
public void onBindViewHolder(@NonNull MyReposListAdapter.MyReposViewHolder holder, int position) { public void onBindViewHolder(@NonNull MyReposListAdapter.MyReposViewHolder holder, int position) {
TinyDB tinyDb = TinyDB.getInstance(context);
UserRepositories currentItem = reposList.get(position); UserRepositories currentItem = reposList.get(position);
holder.repoDescription.setVisibility(View.GONE); int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
holder.repoBranch.setText(currentItem.getDefault_branch());
holder.htmlUrl.setText(currentItem.getHtml_url()); 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; ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName()); 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); 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() != null) {
if(!currentItem.getAvatar_url().equals("")) { 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 { else {
holder.imageAvatar.setImageDrawable(drawable); holder.image.setImageDrawable(drawable);
} }
} }
else { 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("")) { if(!currentItem.getDescription().equals("")) {
holder.repoDescription.setVisibility(View.VISIBLE); holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription()); holder.repoDescription.setText(currentItem.getDescription());
} holder.spacerView.setVisibility(View.GONE);
holder.repoFullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
} }
else { else {
holder.repoPrivatePublic.setVisibility(View.GONE); holder.repoDescription.setVisibility(View.GONE);
holder.repoType.setText(R.string.strPublic); 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) { if(holder.isRepoAdmin == null) {
holder.isRepoAdmin = new CheckBox(mCtx); holder.isRepoAdmin = new CheckBox(context);
} }
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin()); holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
} }
@Override @Override
@ -329,7 +273,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
return myReposFilter; return myReposFilter;
} }
private Filter myReposFilter = new Filter() { private final Filter myReposFilter = new Filter() {
@Override @Override
protected FilterResults performFiltering(CharSequence constraint) { protected FilterResults performFiltering(CharSequence constraint) {

View File

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

View File

@ -12,12 +12,13 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.UserOrganizations;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.OrganizationDetailActivity; import org.mian.gitnex.activities.OrganizationDetailActivity;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserOrganizations;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -27,42 +28,42 @@ import java.util.List;
public class OrganizationsListAdapter extends RecyclerView.Adapter<OrganizationsListAdapter.OrganizationsViewHolder> implements Filterable { public class OrganizationsListAdapter extends RecyclerView.Adapter<OrganizationsListAdapter.OrganizationsViewHolder> implements Filterable {
private List<UserOrganizations> orgList; private final List<UserOrganizations> orgList;
private Context mCtx; private final Context context;
private List<UserOrganizations> orgListFull; private final List<UserOrganizations> orgListFull;
static class OrganizationsViewHolder extends RecyclerView.ViewHolder { static class OrganizationsViewHolder extends RecyclerView.ViewHolder {
private ImageView image; private UserOrganizations userOrganizations;
private TextView mTextView1;
private TextView mTextView2; private final ImageView image;
private TextView organizationId; private final TextView orgName;
private final TextView orgDescription;
private OrganizationsViewHolder(View itemView) { private OrganizationsViewHolder(View itemView) {
super(itemView); super(itemView);
mTextView1 = itemView.findViewById(R.id.orgUsername); orgName = itemView.findViewById(R.id.orgName);
mTextView2 = itemView.findViewById(R.id.orgDescription); orgDescription = itemView.findViewById(R.id.orgDescription);
image = itemView.findViewById(R.id.imageAvatar); image = itemView.findViewById(R.id.imageAvatar);
organizationId = itemView.findViewById(R.id.organizationId);
itemView.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
Context context = v.getContext(); Context context = v.getContext();
Intent intent = new Intent(context, OrganizationDetailActivity.class); Intent intent = new Intent(context, OrganizationDetailActivity.class);
intent.putExtra("orgName", mTextView1.getText().toString()); intent.putExtra("orgName", userOrganizations.getUsername());
TinyDB tinyDb = TinyDB.getInstance(context); TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("orgName", mTextView1.getText().toString()); tinyDb.putString("orgName", userOrganizations.getUsername());
tinyDb.putString("organizationId", organizationId.getText().toString()); tinyDb.putString("organizationId", String.valueOf(userOrganizations.getId()));
tinyDb.putBoolean("organizationAction", true); tinyDb.putBoolean("organizationAction", true);
context.startActivity(intent); context.startActivity(intent);
}); });
} }
} }
public OrganizationsListAdapter(Context mCtx, List<UserOrganizations> orgsListMain) { public OrganizationsListAdapter(Context ctx, List<UserOrganizations> orgsListMain) {
this.mCtx = mCtx; this.context = ctx;
this.orgList = orgsListMain; this.orgList = orgsListMain;
orgListFull = new ArrayList<>(orgList); orgListFull = new ArrayList<>(orgList);
} }
@ -80,16 +81,19 @@ public class OrganizationsListAdapter extends RecyclerView.Adapter<Organizations
public void onBindViewHolder(@NonNull OrganizationsViewHolder holder, int position) { public void onBindViewHolder(@NonNull OrganizationsViewHolder holder, int position) {
UserOrganizations currentItem = orgList.get(position); UserOrganizations currentItem = orgList.get(position);
holder.mTextView2.setVisibility(View.GONE); int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
holder.organizationId.setText(Integer.toString(currentItem.getId()));
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.userOrganizations = currentItem;
holder.mTextView1.setText(currentItem.getUsername()); holder.orgName.setText(currentItem.getUsername());
if (!currentItem.getDescription().equals("")) { 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);
holder.mTextView2.setVisibility(View.VISIBLE); if(!currentItem.getDescription().equals("")) {
holder.mTextView2.setText(currentItem.getDescription()); holder.orgDescription.setVisibility(View.VISIBLE);
holder.orgDescription.setText(currentItem.getDescription());
}
else {
holder.orgDescription.setVisibility(View.GONE);
} }
} }

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();
}
}

View File

@ -3,23 +3,26 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.text.HtmlCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.PullRequests;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity; import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener; import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper; import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.PullRequests;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -29,17 +32,15 @@ import java.util.Locale;
public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context; private final Context context;
private final int TYPE_LOAD = 0; private final int TYPE_LOAD = 0;
private List<PullRequests> prList; private List<PullRequests> prList;
private PullRequestsAdapter.OnLoadMoreListener loadMoreListener; private PullRequestsAdapter.OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true; private boolean isLoading = false, isMoreDataAvailable = true;
public PullRequestsAdapter(Context context, List<PullRequests> prListMain) { public PullRequestsAdapter(Context context, List<PullRequests> prListMain) {
this.context = context; this.context = context;
this.prList = prListMain; this.prList = prListMain;
} }
@NonNull @NonNull
@ -54,7 +55,6 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
else { else {
return new PullRequestsAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false)); return new PullRequestsAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
} }
} }
@Override @Override
@ -64,15 +64,11 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
isLoading = true; isLoading = true;
loadMoreListener.onLoadMore(); loadMoreListener.onLoadMore();
} }
if(getItemViewType(position) == TYPE_LOAD) { if(getItemViewType(position) == TYPE_LOAD) {
((PullRequestsAdapter.PullRequestsHolder) holder).bindData(prList.get(position)); ((PullRequestsAdapter.PullRequestsHolder) holder).bindData(prList.get(position));
} }
} }
@Override @Override
@ -84,172 +80,125 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
else { else {
return 1; return 1;
} }
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return prList.size(); return prList.size();
} }
class PullRequestsHolder extends RecyclerView.ViewHolder { class PullRequestsHolder extends RecyclerView.ViewHolder {
private TextView prNumber; private PullRequests pullRequest;
private TextView prMergeable;
private TextView prHeadBranch; private final ImageView assigneeAvatar;
private TextView prIsFork; private final TextView prTitle;
private TextView prForkFullName; private final TextView prCreatedTime;
private ImageView assigneeAvatar; private final TextView prCommentsCount;
private TextView prTitle;
private TextView prCreatedTime;
private TextView prCommentsCount;
PullRequestsHolder(View itemView) { PullRequestsHolder(View itemView) {
super(itemView); super(itemView);
prNumber = itemView.findViewById(R.id.prNumber);
prMergeable = itemView.findViewById(R.id.prMergeable);
prHeadBranch = itemView.findViewById(R.id.prHeadBranch);
prIsFork = itemView.findViewById(R.id.prIsFork);
prForkFullName = itemView.findViewById(R.id.prForkFullName);
assigneeAvatar = itemView.findViewById(R.id.assigneeAvatar); assigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
prTitle = itemView.findViewById(R.id.prTitle); prTitle = itemView.findViewById(R.id.prTitle);
prCommentsCount = itemView.findViewById(R.id.prCommentsCount); prCommentsCount = itemView.findViewById(R.id.prCommentsCount);
LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount);
prCreatedTime = itemView.findViewById(R.id.prCreatedTime); prCreatedTime = itemView.findViewById(R.id.prCreatedTime);
prTitle.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class); Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", prNumber.getText()); intent.putExtra("issueNumber", pullRequest.getNumber());
intent.putExtra("prMergeable", prMergeable.getText()); intent.putExtra("prMergeable", pullRequest.isMergeable());
intent.putExtra("prHeadBranch", prHeadBranch.getText()); intent.putExtra("prHeadBranch", pullRequest.getHead().getRef());
TinyDB tinyDb = TinyDB.getInstance(context); TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("issueNumber", prNumber.getText().toString()); tinyDb.putString("issueNumber", String.valueOf(pullRequest.getNumber()));
tinyDb.putString("prMergeable", prMergeable.getText().toString()); tinyDb.putString("prMergeable", String.valueOf(pullRequest.isMergeable()));
tinyDb.putString("prHeadBranch", prHeadBranch.getText().toString()); tinyDb.putString("prHeadBranch", pullRequest.getHead().getRef());
tinyDb.putString("prIsFork", prIsFork.getText().toString());
tinyDb.putString("prForkFullName", prForkFullName.getText().toString());
tinyDb.putString("issueType", "Pull");
context.startActivity(intent);
}); if(pullRequest.getHead() != null && pullRequest.getHead().getRepo() != null) {
frameCommentsCount.setOnClickListener(v -> { tinyDb.putString("prIsFork", String.valueOf(pullRequest.getHead().getRepo().isFork()));
tinyDb.putString("prForkFullName", pullRequest.getHead().getRepo().getFull_name());
Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", prNumber.getText());
intent.putExtra("prMergeable", prMergeable.getText());
intent.putExtra("prHeadBranch", prHeadBranch.getText());
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("issueNumber", prNumber.getText().toString());
tinyDb.putString("prMergeable", prMergeable.getText().toString());
tinyDb.putString("prHeadBranch", prHeadBranch.getText().toString());
tinyDb.putString("prIsFork", prIsFork.getText().toString());
tinyDb.putString("prForkFullName", prForkFullName.getText().toString());
tinyDb.putString("issueType", "Pull");
context.startActivity(intent);
});
}
@SuppressLint("SetTextI18n")
void bindData(PullRequests prModel) {
final TinyDB tinyDb = TinyDB.getInstance(context);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
if(!prModel.getUser().getFull_name().equals("")) {
assigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.prCreator) + prModel.getUser().getFull_name(), context));
}
else {
assigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.prCreator) + prModel.getUser().getLogin(), context));
}
if(prModel.getUser().getAvatar_url() != null) {
PicassoService.getInstance(context).get().load(prModel.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar);
}
else {
PicassoService.getInstance(context).get().load(prModel.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar);
}
String prNumber_ = "<font color='" + context.getResources().getColor(R.color.lightGray) + "'>" + context.getResources().getString(R.string.hash) + prModel.getNumber() + "</font>";
prTitle.setText(Html.fromHtml(prNumber_ + " " + prModel.getTitle()));
prNumber.setText(String.valueOf(prModel.getNumber()));
prMergeable.setText(String.valueOf(prModel.isMergeable()));
if(prModel.getHead() != null) {
prHeadBranch.setText(prModel.getHead().getRef());
if(prModel.getHead().getRepo() != null) {
prIsFork.setText(String.valueOf(prModel.getHead().getRepo().isFork()));
prForkFullName.setText(prModel.getHead().getRepo().getFull_name());
} }
else { else {
// pull was done from a deleted fork // pull was done from a deleted fork
prIsFork.setText("true"); tinyDb.putString("prIsFork", "true");
prForkFullName.setText(context.getString(R.string.prDeletedFrok)); tinyDb.putString("prForkFullName", context.getString(R.string.prDeletedFork));
} }
}
prCommentsCount.setText(String.valueOf(prModel.getComments()));
prCreatedTime.setText(TimeHelper.formatTime(prModel.getCreated_at(), new Locale(locale), timeFormat, context)); tinyDb.putString("issueType", "Pull");
context.startActivity(intent);
});
assigneeAvatar.setOnClickListener(v -> {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", pullRequest.getUser().getLogin());
context.startActivity(intent);
});
assigneeAvatar.setOnLongClickListener(loginId -> {
AppUtil.copyToClipboard(context, pullRequest.getUser().getLogin(), context.getString(R.string.copyLoginIdToClipBoard, pullRequest.getUser().getLogin()));
return true;
});
}
@SuppressLint("SetTextI18n")
void bindData(PullRequests pullRequest) {
TinyDB tinyDb = TinyDB.getInstance(context);
Locale locale = context.getResources().getConfiguration().locale;
String timeFormat = tinyDb.getString("dateFormat");
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
PicassoService.getInstance(context).get()
.load(pullRequest.getUser().getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(imgRadius, 0))
.resize(120, 120)
.centerCrop()
.into(this.assigneeAvatar);
this.pullRequest = pullRequest;
String prNumber_ = "<font color='" + ResourcesCompat.getColor(context.getResources(), R.color.lightGray, null) + "'>" + context.getResources().getString(R.string.hash) + pullRequest.getNumber() + "</font>";
this.prTitle.setText(HtmlCompat.fromHtml(prNumber_ + " " + EmojiParser.parseToUnicode(pullRequest.getTitle()), HtmlCompat.FROM_HTML_MODE_LEGACY));
this.prCommentsCount.setText(String.valueOf(pullRequest.getComments()));
this.prCreatedTime.setText(TimeHelper.formatTime(pullRequest.getCreated_at(), locale, timeFormat, context));
if(timeFormat.equals("pretty")) { if(timeFormat.equals("pretty")) {
prCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(prModel.getCreated_at()), context)); this.prCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(pullRequest.getCreated_at()), context));
} }
} }
} }
static class LoadHolder extends RecyclerView.ViewHolder { static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) { LoadHolder(View itemView) {
super(itemView); super(itemView);
} }
} }
public void setMoreDataAvailable(boolean moreDataAvailable) { public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable; isMoreDataAvailable = moreDataAvailable;
} }
public void notifyDataChanged() { public void notifyDataChanged() {
notifyDataSetChanged(); notifyDataSetChanged();
isLoading = false; isLoading = false;
} }
public interface OnLoadMoreListener { public interface OnLoadMoreListener {
void onLoadMore(); void onLoadMore();
} }
public void setLoadMoreListener(PullRequestsAdapter.OnLoadMoreListener loadMoreListener) { public void setLoadMoreListener(PullRequestsAdapter.OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener; this.loadMoreListener = loadMoreListener;
} }
public void updateList(List<PullRequests> list) { public void updateList(List<PullRequests> list) {
prList = list; prList = list;
notifyDataSetChanged(); notifyDataSetChanged();
} }
} }

View File

@ -1,26 +1,28 @@
package org.mian.gitnex.adapters; package org.mian.gitnex.adapters;
import android.content.Context; import android.content.Context;
import android.text.Html; import android.content.Intent;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.text.HtmlCompat;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.Releases;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener; import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.Markdown; import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper; import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Releases;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -30,25 +32,26 @@ import java.util.Locale;
public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.ReleasesViewHolder> { public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.ReleasesViewHolder> {
private List<Releases> releasesList; private final List<Releases> releasesList;
private Context mCtx; private final Context context;
static class ReleasesViewHolder extends RecyclerView.ViewHolder { static class ReleasesViewHolder extends RecyclerView.ViewHolder {
private TextView releaseType; private Releases releases;
private TextView releaseName;
private ImageView authorAvatar; private final TextView releaseType;
private TextView authorName; private final TextView releaseName;
private TextView releaseTag; private final ImageView authorAvatar;
private TextView releaseCommitSha; private final TextView authorName;
private TextView releaseDate; private final TextView releaseTag;
private TextView releaseBodyContent; private final TextView releaseDate;
private LinearLayout downloadFrame; private final TextView releaseBodyContent;
private RelativeLayout downloads; private final LinearLayout downloadFrame;
private TextView releaseZipDownload; private final LinearLayout downloads;
private TextView releaseTarDownload; private final TextView releaseZipDownload;
private ImageView downloadDropdownIcon; private final TextView releaseTarDownload;
private RecyclerView downloadList; private final ImageView downloadDropdownIcon;
private final RecyclerView downloadList;
private ReleasesViewHolder(View itemView) { private ReleasesViewHolder(View itemView) {
@ -59,7 +62,7 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
authorAvatar = itemView.findViewById(R.id.authorAvatar); authorAvatar = itemView.findViewById(R.id.authorAvatar);
authorName = itemView.findViewById(R.id.authorName); authorName = itemView.findViewById(R.id.authorName);
releaseTag = itemView.findViewById(R.id.releaseTag); releaseTag = itemView.findViewById(R.id.releaseTag);
releaseCommitSha = itemView.findViewById(R.id.releaseCommitSha); TextView releaseCommitSha = itemView.findViewById(R.id.releaseCommitSha);
releaseDate = itemView.findViewById(R.id.releaseDate); releaseDate = itemView.findViewById(R.id.releaseDate);
releaseBodyContent = itemView.findViewById(R.id.releaseBodyContent); releaseBodyContent = itemView.findViewById(R.id.releaseBodyContent);
downloadFrame = itemView.findViewById(R.id.downloadFrame); downloadFrame = itemView.findViewById(R.id.downloadFrame);
@ -72,11 +75,18 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
downloadList.setHasFixedSize(true); downloadList.setHasFixedSize(true);
downloadList.setLayoutManager(new LinearLayoutManager(itemView.getContext())); downloadList.setLayoutManager(new LinearLayoutManager(itemView.getContext()));
authorAvatar.setOnClickListener(loginId -> {
Context context = loginId.getContext();
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra("username", releases.getAuthor().getLogin());
context.startActivity(intent);
});
} }
} }
public ReleasesAdapter(Context mCtx, List<Releases> releasesMain) { public ReleasesAdapter(Context ctx, List<Releases> releasesMain) {
this.mCtx = mCtx; this.context = ctx;
this.releasesList = releasesMain; this.releasesList = releasesMain;
} }
@ -90,11 +100,13 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
@Override @Override
public void onBindViewHolder(@NonNull ReleasesAdapter.ReleasesViewHolder holder, int position) { public void onBindViewHolder(@NonNull ReleasesAdapter.ReleasesViewHolder holder, int position) {
final TinyDB tinyDb = TinyDB.getInstance(mCtx); final TinyDB tinyDb = TinyDB.getInstance(context);
final String locale = tinyDb.getString("locale"); final Locale locale = context.getResources().getConfiguration().locale;
final String timeFormat = tinyDb.getString("dateFormat"); final String timeFormat = tinyDb.getString("dateFormat");
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
Releases currentItem = releasesList.get(position); Releases currentItem = releasesList.get(position);
holder.releases = currentItem;
holder.releaseName.setText(currentItem.getName()); holder.releaseName.setText(currentItem.getName());
@ -111,25 +123,25 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
} }
if(currentItem.getAuthor().getAvatar_url() != null) { if(currentItem.getAuthor().getAvatar_url() != null) {
PicassoService.getInstance(mCtx).get().load(currentItem.getAuthor().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.authorAvatar); PicassoService.getInstance(context).get().load(currentItem.getAuthor().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(holder.authorAvatar);
} }
holder.authorName.setText(mCtx.getResources().getString(R.string.releasePublishedBy, currentItem.getAuthor().getUsername())); holder.authorName.setText(context.getResources().getString(R.string.releasePublishedBy, currentItem.getAuthor().getUsername()));
if(currentItem.getTag_name() != null) { if(currentItem.getTag_name() != null) {
holder.releaseTag.setText(currentItem.getTag_name()); holder.releaseTag.setText(currentItem.getTag_name());
} }
if(currentItem.getPublished_at() != null) { if(currentItem.getPublished_at() != null) {
holder.releaseDate.setText(TimeHelper.formatTime(currentItem.getPublished_at(), new Locale(locale), timeFormat, mCtx)); holder.releaseDate.setText(TimeHelper.formatTime(currentItem.getPublished_at(), locale, timeFormat, context));
} }
if(timeFormat.equals("pretty")) { if(timeFormat.equals("pretty")) {
holder.releaseDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getPublished_at()), mCtx)); holder.releaseDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getPublished_at()), context));
} }
if(!currentItem.getBody().equals("")) { if(!currentItem.getBody().equals("")) {
new Markdown(mCtx, currentItem.getBody(), holder.releaseBodyContent); Markdown.render(context, currentItem.getBody(), holder.releaseBodyContent);
} }
else { else {
holder.releaseBodyContent.setText(R.string.noReleaseBodyContent); holder.releaseBodyContent.setText(R.string.noReleaseBodyContent);
@ -141,28 +153,25 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
holder.downloadDropdownIcon.setImageResource(R.drawable.ic_chevron_down); holder.downloadDropdownIcon.setImageResource(R.drawable.ic_chevron_down);
holder.downloads.setVisibility(View.VISIBLE); holder.downloads.setVisibility(View.VISIBLE);
} }
else { else {
holder.downloadDropdownIcon.setImageResource(R.drawable.ic_chevron_right); holder.downloadDropdownIcon.setImageResource(R.drawable.ic_chevron_right);
holder.downloads.setVisibility(View.GONE); holder.downloads.setVisibility(View.GONE);
} }
}); });
holder.releaseZipDownload.setText( holder.releaseZipDownload.setText(
Html.fromHtml("<a href='" + currentItem.getZipball_url() + "'>" + mCtx.getResources().getString(R.string.zipArchiveDownloadReleasesTab) + "</a> ")); HtmlCompat.fromHtml("<a href='" + currentItem.getZipball_url() + "'>" + context.getResources().getString(R.string.zipArchiveDownloadReleasesTab) + "</a> ", HtmlCompat.FROM_HTML_MODE_LEGACY));
holder.releaseZipDownload.setMovementMethod(LinkMovementMethod.getInstance()); holder.releaseZipDownload.setMovementMethod(LinkMovementMethod.getInstance());
holder.releaseTarDownload.setText( holder.releaseTarDownload.setText(
Html.fromHtml("<a href='" + currentItem.getTarball_url() + "'>" + mCtx.getResources().getString(R.string.tarArchiveDownloadReleasesTab) + "</a> ")); HtmlCompat.fromHtml("<a href='" + currentItem.getTarball_url() + "'>" + context.getResources().getString(R.string.tarArchiveDownloadReleasesTab) + "</a> ", HtmlCompat.FROM_HTML_MODE_LEGACY));
holder.releaseTarDownload.setMovementMethod(LinkMovementMethod.getInstance()); holder.releaseTarDownload.setMovementMethod(LinkMovementMethod.getInstance());
ReleasesDownloadsAdapter adapter = new ReleasesDownloadsAdapter(currentItem.getAssets()); ReleasesDownloadsAdapter adapter = new ReleasesDownloadsAdapter(currentItem.getAssets());
holder.downloadList.setAdapter(adapter); holder.downloadList.setAdapter(adapter);
} }
@Override @Override

View File

@ -1,15 +1,15 @@
package org.mian.gitnex.adapters; package org.mian.gitnex.adapters;
import android.text.Html;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.text.HtmlCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.Releases;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.models.Releases;
import java.util.List; import java.util.List;
/** /**
@ -18,18 +18,16 @@ import java.util.List;
public class ReleasesDownloadsAdapter extends RecyclerView.Adapter<ReleasesDownloadsAdapter.ReleasesDownloadsViewHolder> { public class ReleasesDownloadsAdapter extends RecyclerView.Adapter<ReleasesDownloadsAdapter.ReleasesDownloadsViewHolder> {
private List<Releases.assetsObject> releasesDownloadsList; private final List<Releases.assetsObject> releasesDownloadsList;
static class ReleasesDownloadsViewHolder extends RecyclerView.ViewHolder { static class ReleasesDownloadsViewHolder extends RecyclerView.ViewHolder {
private TextView downloadName; private final TextView downloadName;
private ReleasesDownloadsViewHolder(View itemView) { private ReleasesDownloadsViewHolder(View itemView) {
super(itemView); super(itemView);
downloadName = itemView.findViewById(R.id.downloadName); downloadName = itemView.findViewById(R.id.downloadName);
} }
} }
@ -53,11 +51,10 @@ public class ReleasesDownloadsAdapter extends RecyclerView.Adapter<ReleasesDownl
if(currentItem.getName() != null) { if(currentItem.getName() != null) {
holder.downloadName.setText( holder.downloadName.setText(
Html.fromHtml("<a href='" + currentItem.getBrowser_download_url() + "'>" + currentItem.getName() + "</a> ")); HtmlCompat.fromHtml("<a href='" + currentItem.getBrowser_download_url() + "'>" + currentItem.getName() + "</a> ", HtmlCompat.FROM_HTML_MODE_LEGACY));
holder.downloadName.setMovementMethod(LinkMovementMethod.getInstance()); holder.downloadName.setMovementMethod(LinkMovementMethod.getInstance());
} }
} }
@Override @Override

View File

@ -9,29 +9,31 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator; 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.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity; 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.PicassoService;
import org.mian.gitnex.clients.RetrofitClient; 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.RepositoriesApi;
import org.mian.gitnex.database.models.Repository; 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.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories; import org.ocpsoft.prettytime.PrettyTime;
import org.mian.gitnex.models.WatchInfo; import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List; import java.util.List;
import java.util.Locale;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -41,7 +43,7 @@ import retrofit2.Callback;
public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context ctx; private final Context context;
private final int TYPE_LOAD = 0; private final int TYPE_LOAD = 0;
private List<UserRepositories> forksList; private List<UserRepositories> forksList;
private OnLoadMoreListener loadMoreListener; private OnLoadMoreListener loadMoreListener;
@ -50,16 +52,15 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
public RepoForksAdapter(Context ctx, List<UserRepositories> forksListMain) { public RepoForksAdapter(Context ctx, List<UserRepositories> forksListMain) {
this.ctx = ctx; this.context = ctx;
this.forksList = forksListMain; this.forksList = forksListMain;
} }
@NonNull @NonNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(ctx); LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) { if(viewType == TYPE_LOAD) {
return new RepoForksAdapter.ForksHolder(inflater.inflate(R.layout.list_repositories, parent, false)); return new RepoForksAdapter.ForksHolder(inflater.inflate(R.layout.list_repositories, parent, false));
@ -67,7 +68,6 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
else { else {
return new LoadHolder(inflater.inflate(R.layout.row_load, parent, false)); return new LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
} }
} }
@Override @Override
@ -77,15 +77,12 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
isLoading = true; isLoading = true;
loadMoreListener.onLoadMore(); loadMoreListener.onLoadMore();
} }
if(getItemViewType(position) == TYPE_LOAD) { if(getItemViewType(position) == TYPE_LOAD) {
((RepoForksAdapter.ForksHolder) holder).bindData(forksList.get(position)); ((RepoForksAdapter.ForksHolder) holder).bindData(forksList.get(position));
} }
} }
@Override @Override
@ -97,69 +94,63 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
else { else {
return 1; return 1;
} }
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return forksList.size(); return forksList.size();
} }
class ForksHolder extends RecyclerView.ViewHolder { class ForksHolder extends RecyclerView.ViewHolder {
private ImageView image; private UserRepositories userRepositories;
private TextView repoName;
private TextView repoDescription; private final ImageView image;
private TextView fullName; private final TextView repoName;
private final TextView orgName;
private final TextView repoDescription;
private CheckBox isRepoAdmin; private CheckBox isRepoAdmin;
private ImageView repoPrivatePublic; private final TextView repoStars;
private TextView repoStars; private final TextView repoLastUpdated;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private LinearLayout archiveRepo;
private TextView repoBranch;
private ImageView reposDropdownMenu;
ForksHolder(View itemView) { ForksHolder(View itemView) {
super(itemView); super(itemView);
repoName = itemView.findViewById(R.id.repoName); repoName = itemView.findViewById(R.id.repoName);
orgName = itemView.findViewById(R.id.orgName);
repoDescription = itemView.findViewById(R.id.repoDescription); repoDescription = itemView.findViewById(R.id.repoDescription);
isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin); isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin);
image = itemView.findViewById(R.id.imageAvatar); image = itemView.findViewById(R.id.imageAvatar);
fullName = itemView.findViewById(R.id.repoFullName);
repoPrivatePublic = itemView.findViewById(R.id.imageRepoType);
repoStars = itemView.findViewById(R.id.repoStars); repoStars = itemView.findViewById(R.id.repoStars);
repoForks = itemView.findViewById(R.id.repoForks); repoLastUpdated = itemView.findViewById(R.id.repoLastUpdated);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
repoBranch = itemView.findViewById(R.id.repoBranch);
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
void bindData(UserRepositories forksModel) { void bindData(UserRepositories forksModel) {
repoDescription.setVisibility(View.GONE); TinyDB tinyDb = TinyDB.getInstance(context);
repoBranch.setText(forksModel.getDefault_branch()); int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
Locale locale = context.getResources().getConfiguration().locale;
String timeFormat = tinyDb.getString("dateFormat");
this.userRepositories = forksModel;
orgName.setText(forksModel.getFullName().split("/")[0]);
repoName.setText(forksModel.getFullName().split("/")[1]);
repoStars.setText(forksModel.getStars_count());
ColorGenerator generator = ColorGenerator.MATERIAL; ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(forksModel.getName()); int color = generator.getColor(forksModel.getName());
String firstCharacter = String.valueOf(forksModel.getName().charAt(0)); String firstCharacter = String.valueOf(forksModel.getFullName().charAt(0));
TextDrawable drawable = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT).fontSize(18).toUpperCase().width(28).height(28) TextDrawable drawable = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT).fontSize(18).toUpperCase().width(28).height(28)
.endConfig().buildRoundRect(firstCharacter, color, 3); .endConfig().buildRoundRect(firstCharacter, color, 3);
if(forksModel.getAvatar_url() != null) { if(forksModel.getAvatar_url() != null) {
if(!forksModel.getAvatar_url().equals("")) { if(!forksModel.getAvatar_url().equals("")) {
PicassoService.getInstance(ctx).get().load(forksModel.getAvatar_url()).placeholder(R.drawable.loader_animated) PicassoService.getInstance(context).get().load(forksModel.getAvatar_url()).placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(image); .transform(new RoundedTransformation(imgRadius, 0)).resize(120, 120).centerCrop().into(image);
} }
else { else {
image.setImageDrawable(drawable); image.setImageDrawable(drawable);
@ -169,76 +160,85 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
image.setImageDrawable(drawable); image.setImageDrawable(drawable);
} }
repoName.setText(forksModel.getName()); if(forksModel.getUpdated_at() != null) {
switch(timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(locale);
String createdTime = prettyTime.format(forksModel.getUpdated_at());
repoLastUpdated.setText(context.getString(R.string.lastUpdatedAt, createdTime));
repoLastUpdated.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(forksModel.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(forksModel.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(forksModel.getUpdated_at());
repoLastUpdated.setText(context.getString(R.string.lastUpdatedAt, createdTime));
break;
}
}
}
else {
repoLastUpdated.setVisibility(View.GONE);
}
if(!forksModel.getDescription().equals("")) { if(!forksModel.getDescription().equals("")) {
repoDescription.setVisibility(View.VISIBLE);
repoDescription.setText(forksModel.getDescription()); repoDescription.setText(forksModel.getDescription());
} }
fullName.setText(forksModel.getFullName());
if(forksModel.getPrivateFlag()) {
repoPrivatePublic.setImageResource(R.drawable.ic_lock);
repoType.setText(R.string.strPrivate);
}
else { else {
repoPrivatePublic.setVisibility(View.GONE); repoDescription.setText(context.getString(R.string.noDataDescription));
repoType.setText(R.string.strPublic);
} }
repoStars.setText(forksModel.getStars_count());
repoForks.setText(forksModel.getForks_count());
repoOpenIssuesCount.setText(forksModel.getOpen_issues_count());
if(isRepoAdmin == null) { if(isRepoAdmin == null) {
isRepoAdmin = new CheckBox(ctx); isRepoAdmin = new CheckBox(context);
} }
isRepoAdmin.setChecked(forksModel.getPermissions().isAdmin()); isRepoAdmin.setChecked(forksModel.getPermissions().isAdmin());
if(forksModel.isArchived()) {
archiveRepo.setVisibility(View.VISIBLE);
}
else {
archiveRepo.setVisibility(View.GONE);
}
itemView.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
Context context = v.getContext(); Context context = v.getContext();
TextView repoFullName = v.findViewById(R.id.repoFullName);
TextView repoType_ = v.findViewById(R.id.repoType);
Intent intent = new Intent(context, RepoDetailActivity.class); Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", repoFullName.getText().toString()); intent.putExtra("repoFullName", userRepositories.getFullName());
TinyDB tinyDb = TinyDB.getInstance(context); tinyDb.putString("repoFullName", userRepositories.getFullName());
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putString("repoType", repoType_.getText().toString());
//tinyDb.putBoolean("resumeIssues", true); //tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked()); 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 repoOwner = parts[0];
final String repoName = parts[1]; final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId"); int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context); RepositoriesApi repositoryData = BaseApi.getInstance(context, RepositoriesApi.class);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId); //RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
assert repositoryData != null;
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName); Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) { if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName); long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id); tinyDb.putLong("repositoryId", id);
} }
else { else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName); Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId()); tinyDb.putLong("repositoryId", data.getRepositoryId());
} }
//store if user is watching this repo //store if user is watching this repo
@ -291,63 +291,6 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
context.startActivity(intent); 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 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();
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(watchers -> {
Intent intentW = new Intent(context, RepoForksActivity.class);
intentW.putExtra("repoFullNameForForks", fullName.getText());
context.startActivity(intentW);
dialog.dismiss();
});
});
} }
} }
@ -358,32 +301,27 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
super(itemView); super(itemView);
} }
} }
public void setMoreDataAvailable(boolean moreDataAvailable) { public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable; isMoreDataAvailable = moreDataAvailable;
} }
public void notifyDataChanged() { public void notifyDataChanged() {
notifyDataSetChanged(); notifyDataSetChanged();
isLoading = false; isLoading = false;
} }
public interface OnLoadMoreListener { public interface OnLoadMoreListener {
void onLoadMore(); void onLoadMore();
} }
public void setLoadMoreListener(RepoForksAdapter.OnLoadMoreListener loadMoreListener) { public void setLoadMoreListener(RepoForksAdapter.OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener; this.loadMoreListener = loadMoreListener;
} }
public void updateList(List<UserRepositories> list) { public void updateList(List<UserRepositories> list) {

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