Compare commits

...

167 Commits

Author SHA1 Message Date
030498f360 Release 3.3.0 (#780)
Release 3.3.0

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/780
2020-11-18 08:19:52 +01:00
0fd072611b Fix add new account (#778)
Fix add new account

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/778
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-11-17 19:55:49 +01:00
7aec99641e Update Translations 2020-11-16 (#775) (#776)
Merge branch 'release-3.3' into backport_775

Update Translations 2020-11-16 (#775)

Update Translations 2020-11-16

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/775
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/776
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-11-17 14:53:50 +01:00
40f909e46b Fix date and minor ui improvements (#773)
Fix date and minor ui improvements

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/773
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-11-17 05:40:14 +01:00
240cdf5701 Fix pr pagination (#770)
links improvement

Fix button alignment in polling delay popup

Fix pr pagination

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

Add commit to deep links

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

Using JitPack for artifact instead.

Fixing missing emotes.

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

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

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

Improving color of selected elements.

First, fully working implementation of reactions.

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

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

(Hopefully) fixing merge issues.

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

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

Moving reactions below time frame on comments.

Merge branch 'master' into layout-reactions

Add IssueReactions

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

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

Merge branch 'master' into layout-reactions

Applying to pulls and issues.

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

Providing external layouts.

Some improvements.

Adding comment emote indications.

Adding circle around emotes.

Adding some padding.

First tests.

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

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

Minor cleanups.

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

Fix repo size

Add new instances

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

Add org level labels to issue labels

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

Adding option to enable/disable notifications.

Fix typos

Improve notifications

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

refactor deeplinks

Add popular instances taken from #758

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

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

Fixing theme recognition.

Merge branch 'master' into performance-highlight-refactor

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

Add new field issueType to db

Improving theme recognition.

Fixing alignment of menu button.

Fixing cut off text.

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

Fixing crash.

Refactoring activities.

Improving drafts.

Calculating density for avatars.

Improving drafts.

Calculating density for avatars.

Increasing size of avatar.

Decreasing size of avatar.

Restoring DeepLinksActivity

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

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

Initial commit.

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

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

remove liberapay

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

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

Fix scrolling issue for textareas

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

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

Merge branch 'master' into improving-templates

Improving templates.

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

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

Cleanup and refactor of activities

Fix bottomsheet

enhance code blocks and refactors

Move home screen to general, make it ready for translation

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

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

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

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

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

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/740
2020-10-28 13:36:07 +01:00
d3fe4d6d41 3.3.0 rc release (#734)
Prepare 3.3.0 rc release

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/734
2020-10-25 12:46:25 +01:00
8e86fa668d Handle popular links (#730)
Fix settings layout

Merge branch 'master' into deeplinks

Support for all links, check gitea instance, add progress indicator

Enhance account checks, improve the experience of coming from links

Merge branch 'master' into deeplinks

Update libs

Minor layout fixes

gradle update

Fix show/hide views

Handle pr, repos. Handle settings for no action.

open issue from link

Add new settings section translation ready - General for generic settings

wip on handle popular links

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: 6543 <6543@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/730
2020-10-23 20:13:13 +02:00
044f6191bf New input design (#725)
Update missing buttons

update libs

login screen

Merge pr screen

create new file screen

This will be replaced later by custom built mentions, so removing the dependency.

create repo screen

comment screen

edit issue/pr screen and minor ui fixes

collaborator screen

release screen

label and milestone screens

move org, new team, new team member to new design

Add new user input transition

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/725
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-10-20 20:09:07 +02:00
9e19945ad4 Add source of installation (#732)
Add source of installation

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/732
2020-10-17 07:36:44 +02:00
cafb29f8b7 Implementing BottomSheetFragment for commenting on issues and pull requests. (#555)
change to server error on onFailure

Fix keyboard move issue

Fix statusbar color, remove social, enhance other things

Merge branch 'master' into bottomsheet-issue-comments

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

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

Making it work.

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

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

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

First major changes.

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

Cleanup.

Simplifying title.

Adding BottomSheetFragment layout for future changes.

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: opyale <opyale@noreply.gitea.io>
Co-authored-by: opyale <example@example.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/555
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-10-12 20:11:23 +02:00
d346d68b4f Fix screen orientation reloads (#728)
Fix screen orientation reloads

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/728
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-10-11 21:49:30 +02:00
57f0d23ef0 New popup for labels/assignees (#723)
Preventing lists to store duplicate collaborators (#726)

Using login instead of id.

Merge branch 'new-popup-labels-assigness' of https://codeberg.org/gitnex/GitNex into new-popup-labels-assigness

To prevent lists storing duplicate Collaborators

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/726

Add current logged user to list

Change to collection

Fix depricated handler calls

Change to List and better naming

Move to actions

Merge branch 'master' into new-popup-labels-assigness

Add assignees popup and remove multi select

update to view binding

add/remove labels in edit issue

remove org call

Add org members to assignees list

Add assignees adapter

Add color to labels

Refactor and add new labels popup

Clean up build libs

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/723
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-10-09 17:47:52 +02:00
1e30c37d7c Improve repo files (#719)
Merge branch 'master' into improve-files

Improve repo files

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/719
2020-10-08 20:44:38 +02:00
1bf023357b Development of 3.3.0 (#722)
Development of 3.3.0

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/722
2020-10-05 18:29:19 +02:00
3235caf07d Add graphics for f-droid (#721)
Add graphics for f-droid

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/721
2020-10-05 17:36:54 +02:00
0f014c2822 Update readme (#718)
Update readme

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/718
2020-09-30 21:15:11 +02:00
996983d7a3 Release 3.2.0 (#717)
Prepare release 3.2.0

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/717
2020-09-30 21:08:48 +02:00
00cfcbc9cf Crowdin 2020-09-30 (#716)
Crowdin 2020-09-30

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/716
2020-09-30 20:45:50 +02:00
74669a9dcb Enhance explore repos (#715)
Enhance explore repos

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/715
2020-09-30 16:53:31 +02:00
d52d7a188e Search issues (#713)
Implement pagination

Use tabs for explore

add fragment, layout, adapter and implementation of api calls

Merge branch 'master' into 14-search-issues-pulls

Merge branch 'master' into 14-search-issues-pulls

Merge branch 'master' into 14-search-issues-pulls

Add menu item

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/713
2020-09-30 13:09:24 +02:00
d20a773d1d Extend explore repositories search (#703)
Merge branch 'master' into improve-explore-screen

improve email address input ui

Add filter query actions

Add radio buttons

improve nav accounts list images

Merge branch 'master' into improve-explore-screen

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

Implement dialog and use new input layout

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/703
2020-09-27 09:55:59 +02:00
bf19e52799 Move about and rate to settings screen (#714)
Move about and rate to settings screen

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/714
2020-09-27 09:36:57 +02:00
8612258174 Including releases in latest builds (#712)
Including releases in latest builds.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/712
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-09-27 00:23:06 +02:00
a31abf0974 3.2.0 rc1 release (#709)
prepare 3.2.0 rc1 release

RC1 release of 3.2.0

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/709
2020-09-26 20:51:12 +02:00
6d466e2542 Crowdin 2020-09-26 (#711)
Crowdin Update

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/711
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-09-26 20:50:15 +02:00
01bd61ad8e Fixing CI (#710)
Fixing CI.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/710
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-09-26 20:21:29 +02:00
4031c32fc8 Introduce Pro version for play store (#708)
Introduce Pro version for play store

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/708
2020-09-26 17:05:51 +02:00
d51d2d5164 Android 11 support (#707)
update libs

Android 11 support

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/707
2020-09-26 15:55:30 +02:00
7b8bc21a83 Adjust logo with new colors (#706)
Adjust logo with new colors

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/706
2020-09-26 09:18:41 +02:00
1c1f73eafc Redo About screen UI and some refactors (#705)
Redo About screen UI and some refactors

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/705
2020-09-26 07:54:31 +02:00
02672aef3d Refactor: remove instanceUrlWithProtocol (#698)
Refactor: remove instanceUrlWithProtocol

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/698
2020-09-24 18:53:28 +02:00
23fb1ce71f Create PR (#689)
Merge branch 'master' into create-pr

consistent button height

implement create pr

Merge branch 'master' into create-pr

Remove save button for labels

minor improvements

new line

Implement interfaces for labels data

UI updates to labels dialog

Merge branch 'master' into create-pr

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Add labels list

Add ui elements, api calls for branches and milestone

Add activity, layout, click trigger and checks

Merge branch 'master' into create-pr

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Add bs item

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

endline

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/689
2020-09-24 18:51:20 +02:00
1f5eeb5632 Notification badge in navigation menu (#702)
Merge branch 'master' into 700-notifications-counter

Notification badge in navigation menu

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/702
2020-09-18 06:51:41 +02:00
78782d159a UI improvements (#699)
UI improvements

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/699
2020-09-16 20:03:52 +02:00
a75ffe0381 Transfer repository ownership (#696)
simplify comments

Transfer repository ownership

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/696
2020-09-16 08:53:13 +02:00
c4279dcd77 Improve crash report notification string (#697)
Improve crash report notification string

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/697
2020-09-16 08:52:32 +02:00
14b1256ce1 Crowdin 2020-09-13 (#694)
Add Czech

Update 2020-09-13

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/694
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-09-13 13:11:55 +02:00
7b72815bcb Add account new UI (#692)
Merge branch 'new-account-ui' of codeberg.org:gitnex/GitNex into new-account-ui

Merge branch 'master' into new-account-ui

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Merge branch 'master' into new-account-ui

Transition of adding account to new UI

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

endline

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/692
2020-09-13 06:57:04 +02:00
5e6c600e71 Repo settings (delete-edit) (#683)
better var names

remove migration

Merge branch 'repo-settings-delete-migrate-edit' of codeberg.org:gitnex/GitNex into repo-settings-delete-migrate-edit

delete repository

Merge branch 'master' into repo-settings-delete-migrate-edit

Can edit repo properties now

Add progress indicator, call for save

Pull repo info into dialog

Repo properties in custom dialog

settings activity with labels

Merge branch 'master' into repo-settings-delete-migrate-edit

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

add bottom sheet entry

endline

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/683
2020-09-13 06:54:05 +02:00
dbf5be25a5 Add stat indicator pr/issues (#686)
Merge branch 'master' into add-stat-indicator

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Show PR/Issue stat

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

endline

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/686
2020-09-13 06:52:30 +02:00
2bfe0b8d1a Fix create issue crash on label added and removed (#685)
Merge branch 'master' into fix-create-issue-crash

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Fix crash when label added and removed

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

endline

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/685
2020-09-13 06:50:06 +02:00
0c92eb3fa2 Fix active account selector (#687)
Merge branch 'master' into fix-active-account-selector

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Fix active account selector

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

endline

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/687
2020-09-13 06:48:30 +02:00
32f3080283 Fix fragments when view forks from repo info (#688)
Temp fix fragments forks

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

endline

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/688
2020-09-13 06:37:10 +02:00
7342668a1b Fixing gitlab ci releases (#690)
Fixing gitlab ci releases.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/690
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-09-08 20:44:12 +02:00
6f9bbe4c58 Optimizing user accounts list. (#684)
Optimizing user accounts list.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/684
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-09-07 16:29:04 +02:00
b2b42887f7 Move branch commits to files popup (#682)
Move commits to file sub menu

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/682
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-09-05 15:43:29 +02:00
37f622b952 Update libs (#681)
Update libs

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/681
2020-09-04 16:33:59 +02:00
d677c90b01 helper Version: add valid() function (#670)
Merge branch 'master' into VersionValid

format code

introduce Version.valid()

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/670
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-09-04 16:33:37 +02:00
23d3ba7f42 Fix crash on token logins with Require signin view enabled (#678)
Fix crash on token logins with Require signin view enabled

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/678
2020-09-03 19:26:24 +02:00
a42d888eb7 Share only stack trace (#675)
Share only stack trace

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/675
2020-09-03 18:12:53 +02:00
bbcffd67d6 Crowdin 2020-08-28 (#668)
Crowdin 2020-08-28

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/668
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-09-02 21:08:23 +02:00
00eb9c9135 Fix edit comment draft (#661)
Fix edit comment draft

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/661
2020-08-24 12:03:16 +02:00
28a23d30f8 Fix crash on login (#662)
Fix crash on login

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/662
2020-08-24 12:02:45 +02:00
82f874dc37 Official start of 3.2 development (#660)
Official start of 3.2 development

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/660
2020-08-21 20:19:44 +02:00
b60a0e7a92 3.1.0 release (#659)
3.1.0 release

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/659
2020-08-21 18:32:56 +02:00
185bdb863d Crowdin 2020-08-21 (#658)
Crowdin 2020-08-21

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/658
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-08-21 18:20:28 +02:00
da338fcc83 Fix styling radio buttons (#657)
Fix styling radio buttons

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/657
2020-08-21 16:59:54 +02:00
6d8a87358d Copy comment url to clipboard (#655)
Copy comment url to clipboard

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/655
2020-08-21 16:17:48 +02:00
5fc6cdde63 New Retro theme (#654)
New Retro theme

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/654
2020-08-20 18:21:55 +02:00
dc6b1bb5b6 Release 3.1.0 RC2 (#653)
Release 3.1.0 RC2

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/653
2020-08-19 09:07:12 +02:00
8768c87b8a Update missing progress bars (#652)
update missing progress bars

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/652
2020-08-18 19:55:34 +02:00
7caff70946 Edit and delete a file (#626)
update if file is modified on resume

implementation of edit file

Merge branch 'master' into 44-delete-file

Merge branch '44-delete-file' of codeberg.org:gitnex/GitNex into 44-delete-file

Merge branch 'master' into 44-delete-file

# Conflicts:
#	app/src/main/java/org/mian/gitnex/activities/CreateFileActivity.java
#	app/src/main/java/org/mian/gitnex/activities/FileViewActivity.java
#	app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
#	app/src/main/java/org/mian/gitnex/fragments/BottomSheetFileViewerFragment.java

Merge branch 'master' into 44-delete-file

implement delete file

add links to bottomsheet

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/626
2020-08-18 16:37:10 +02:00
76137c56bc Improve drafts ui, add edited comments, create new ones on each call (#628)
Merge branch 'master' into 627-save-edit-draft

# Conflicts:
#	app/src/main/java/org/mian/gitnex/actions/IssueActions.java

Merge branch 'master' into 627-save-edit-draft

Improve drafts, add edited comments, create new ones on each call.

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/628
2020-08-18 16:11:31 +02:00
dcacf1f141 Design Accounts from Nav menu (#648)
Merge branch 'master' into new-account-design

Merge branch 'master' into new-account-design

enhance the dialog UI

Merge branch 'master' into new-account-design

New account design in nav with dialog popup list

New design for accounts accessing

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/648
2020-08-18 16:10:46 +02:00
7585eb4834 Update bug icon (#651)
update bug icon

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/651
2020-08-17 19:08:29 +02:00
7dd231ee95 Set notifications as home srceen (#644) 2020-08-12 09:31:39 +02:00
d5fd6d8cc4 Fix share issue url (#643) 2020-08-12 09:31:06 +02:00
28963bb079 Using language instead of country. (#647)
Using language instead of country.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/647
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-08-11 18:32:30 +02:00
87649ebae8 Introduce new progress indicators (#638)
Add indicator to the rest of fragments/activities

Merge branch 'master' into profress-indicators

# Conflicts:
#	app/src/main/res/layout/activity_credits.xml
#	app/src/main/res/layout/activity_sponsors.xml

wip to remove old indicator

Make dark green as primary color, clean up app files

Introduce new progress indicators

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/638
2020-08-09 10:23:51 +02:00
a92969a47f Fix jumps in drawer when open for all items(icons, user data) (#639)
Fix drawer jumps when open for all items

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/639
2020-08-09 10:23:19 +02:00
d9cd04facf Layout improvements (#637)
Layout improvements

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/637
2020-08-08 17:43:14 +02:00
3eacfe91fe 3.1.0 RC1 release (#636)
3.1.0 RC1 release

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/636
2020-08-07 17:28:39 +02:00
e38d141d38 Quick labels, assignes dialog ui fixes (#635)
labels, assignes dialog ui fixes

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/635
2020-08-07 17:23:04 +02:00
7c40c049d4 Fix email login loop (can login with email again) (#629)
Merge branch 'master' into fix-email-logins

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

cleanup

Fix emails logins loop

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/629
2020-08-06 17:31:31 +02:00
b4b7981722 Open respective content when tap on repo info prs, watchers, forks, stargazers (#632)
Merge branch 'master' into open-repo-info-item

Open respective content when tap on repo info items, prs, watchers, forks, stargazers

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/632
2020-08-06 17:19:37 +02:00
96fad2d73e Copy urls (#631)
fix url open in browser

Copy org and repo url

Copy urls

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/631
2020-08-06 17:18:02 +02:00
24064192e4 Enhance dialog buttons (#633)
switch to outline buttons

Enhance and fix color scheme for dialogs

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/633
2020-08-06 17:17:27 +02:00
12a7b6040b App wide UI changes and refactors (#630)
Enhance and update the buttons across the app, colorful animation on tap

update toasty in view models

update toasty in fragments

update toasty in actions, activities, adapters

Alert dialogs buttons arrangements

strings fixes

switch to fab buttons

remove snackbar

Enhance whole app UI, bring consistency among the elements

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/630
2020-08-06 17:16:51 +02:00
30921ea330 Multiple accounts support (#624)
Title update

Color clean up

switch to another account and update the token at login

Add new account

Add fab button for new account and activity

update libs

Remove account from Manage accounts list

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/624
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-08-04 22:50:04 +02:00
ea36a3f6d6 Repository forks (#606)
Repository forks

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/606
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-29 21:46:58 +02:00
f1ecc42876 Md support in file viewer (#607)
format

implement support for md on tap on icon

show icon for md files only

Add md to top bar

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/607
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-29 20:45:05 +02:00
73e7acfbdf Drop support for login with email (#622)
Drop support for login with email

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/622
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-29 20:28:24 +02:00
a9ad91d954 Fix drafts from notifications view (#618)
Fix drafts when coming from notifications

Fix star/watchers layout

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/618
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-29 20:04:40 +02:00
ff537b79ff BasicAuth Login: Handle existing token (#611)
fix code comment

bugfix

code format

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/611
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-29 16:27:47 +02:00
7efc8650fa Remove unlock for public repos (#605)
Remove unlock for public repos

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/605
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-26 12:01:15 +02:00
a171abc0b8 Official start of 3.1.0 development (#603)
Official start of 3.1.0 development

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/603
2020-07-23 20:17:38 +02:00
0928e936d7 Prepare release (#599)
update  feature list in readme

Merge branch 'master' into 480-update-screenshots

update desc for f-droid

update screenshots, add changelogs

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/599
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-23 19:35:46 +02:00
a29011c6a2 Crowdin 2020-07-23 (#602)
Crowdin Update

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/602
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-23 18:38:18 +02:00
c09fc4988a Support Samsung DeX (#601)
Support Samsung DeX

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/601
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-23 18:37:32 +02:00
39ac49b258 Notifications (#554)
Cleanup

Extending and improving notifications

Using new icons instead

Lowering polling delay to one minute and other improvements

Fixing minor issues

Simplifying progress layout

Fixing bugs and other improvements

Adding translations

Notifications

Co-authored-by: opyale <opyale@noreply.gitea.io>
Co-authored-by: 6543 <6543@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/554
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-22 21:32:42 +02:00
cd55f946f0 Crowdin 2020-07-22 (#597)
Crowdin Update

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/597
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-07-22 14:48:12 +02:00
b529f81115 Fix some bugs (#596)
remove redundant casting

Fix edittext layout when typing(reduce size), fix refresh drafts. Minor improvements

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/596
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-19 15:44:08 +02:00
e6109ef36d Search drafts (#574)
Merge branch 'master' into search-drafts

Merge branch 'master' into search-drafts

Merge branch 'master' into search-drafts

Merge branch 'master' into search-drafts

Merge branch 'master' into search-drafts

Merge branch 'master' into search-drafts

Merge branch 'master' into search-drafts

Merge branch 'master' into search-drafts

Merge branch 'master' into search-drafts

# Conflicts:
#	app/src/main/java/org/mian/gitnex/fragments/DraftsFragment.java

search drafts

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/574
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-19 12:33:58 +02:00
e00fcd846a Add missed icons and improve the ratio of all icons across the app (#592)
Merge branch 'master' into new-missing-icons

Merge branch 'master' into new-missing-icons

Fix background and icon

Fix search bar icons and layout to match the themes

new lines?

Merge branch 'master' into new-missing-icons

Add missed icons, and improve the ratio of all icons across the app

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/592
2020-07-19 12:24:47 +02:00
060c86c090 Add server avatar to user accounts (#594)
Add server avatar to user accounts

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/594
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-19 12:13:37 +02:00
26f54280a1 Add explore and drafts to set as home screen options (#588)
Fix icon cut off sizes

Add explore and drafts to set as home screen options

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/588
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-19 12:05:08 +02:00
8a7923cba7 Fix VersionCheck (#591)
code dedub

Bugfix & Test Correction

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/591
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-07-14 18:20:00 +02:00
673b9f564c Crowdin 2020-07-14 (#590)
crowdin_2020-07-14

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/590
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-14 17:14:06 +02:00
d1be03956c Transition of old icons to new ones (#589)
last set of updates and changes to the icons

Add more icons

WIP : transition of more icons

Switch of icons to new icons for the whole app - WIP

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/589
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-12 19:18:50 +02:00
caa437d5e3 Switch branches (#571)
Fix default branch

Merge branch 'master' into switch-branches

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

update icon

Merge branch 'master' into switch-branches

Merge branch 'master' into switch-branches

update the missing parts

Minor updates

Merge branch 'master' into switch-branches

Merge branch 'master' into switch-branches

# Conflicts:
#	app/src/main/java/org/mian/gitnex/activities/CreateIssueActivity.java
#	app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
#	app/src/main/java/org/mian/gitnex/fragments/BottomSheetRepoFragment.java
#	app/src/main/java/org/mian/gitnex/fragments/FilesFragment.java

Add branch to breadcrumb and dir structure fix

Make change branch work

clean up

Merge branch 'master' into switch-branches

add icon in top bar, add interface listener

Merge branch 'master' into switch-branches

Merge remote-tracking branch 'remotes/main/master' into switch-branches

# Conflicts:
#	app/src/main/java/org/mian/gitnex/activities/LoginActivity.java
#	app/src/main/java/org/mian/gitnex/fragments/ProfileFragment.java
#	app/src/main/java/org/mian/gitnex/helpers/PathsHelper.java

Switching between branches.

Minor fixes

Merge remote-tracking branch 'remotes/main/master' into login-fix

URL parsing, label and other improvements.

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: 6543 <6543@noreply.codeberg.org>
Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/571
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-12 17:14:50 +02:00
25036ce5d2 Remove Unused Locales (#585)
Remove Unused Locales

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/585
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-11 12:49:35 +02:00
a8a34ccc7a New icons (#587)
repo info icons update

Update icons across the app

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/587
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-07-10 22:54:09 +02:00
f87e8020d8 Remove Unused Resources (#586)
Remove Unused Resources

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/586
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-10 12:43:51 +02:00
4d67e63db4 Fix license (#584)
Fix license

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/584
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-07-09 17:42:13 +02:00
3561dde19f Badges and drone fix. (#583)
Removing link

Badges and drone fix.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/583
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-09 15:18:21 +02:00
9c48dec54d Delete drafts [settings] (#576)
Merge branch '450-drafts-settings' of codeberg.org:gitnex/GitNex into 450-drafts-settings

Fix package move

Merge branch 'master' into 450-drafts-settings

Merge branch 'master' into 450-drafts-settings

fix default value save

Delete drafts settings

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/576
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-07-09 13:55:09 +02:00
3d72d68e14 Fixing CI (#582)
Fixing CI

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/582
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-09 13:37:44 +02:00
47b24470e6 Improving CI. (#581)
Improving CI.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/581
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-09 13:29:36 +02:00
1db6a3294b Using GitLab CI. (#580)
Using smaller image and publishing releases.

Fixing things.

Merge branch 'gitlab-ci' of https://codeberg.org/opyale/GitNex into gitlab-ci

Removing eclint.

Merge branch 'master' into gitlab-ci

Only run jobs when master changed.

Using GitLab CI.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/580
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-09 08:55:05 +02:00
500dc019c1 Moving TinyDB and AppUtil to helpers. (#579)
Moving TinyDB and AppUtil to helpers.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/579
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-07-07 19:15:01 +02:00
e2aff890d7 Accounts overview screen (#577)
optimize url string

Overview of accounts in the app

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/577
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-07-07 16:20:43 +02:00
cdfc2cfb9e Implement drafts, introduce Room persistence library for db (#139)
Fix no draft message

translation updates

format improvements

typo update

some renaming refactors

Use better naming convention

remove duplicate source

arrange draft titles

enhance click listener area

Launch drafts from reply screen and clean up

Add message draft saved

update repositories tasks

Update user accounts repository with thread, remove async tasks

remove async task in drafts

update layout, change async to thread in drafts

Merge branch 'master' into pull_139

# Conflicts:
#	app/build.gradle
#	app/src/main/java/org/mian/gitnex/activities/LoginActivity.java

Merge branch 'master' into pull_139

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

Merge branch 'pull_139' of codeberg.org:gitnex/GitNex into pull_139

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

Merge branch 'master' into pull_139

# Conflicts:
#	app/src/main/java/org/mian/gitnex/activities/LoginActivity.java
#	app/src/main/java/org/mian/gitnex/activities/ReplyToIssueActivity.java
#	app/src/main/java/org/mian/gitnex/adapters/MyReposListAdapter.java

Merge branch 'master' into pull_139

Merge branch 'master' into pull_139

Merge branch 'master' into pull_139 and fix conflicts

# Conflicts:
#	app/build.gradle
#	app/src/main/java/org/mian/gitnex/activities/LoginActivity.java
#	app/src/main/java/org/mian/gitnex/activities/MainActivity.java
#	app/src/main/java/org/mian/gitnex/activities/ReplyToIssueActivity.java
#	app/src/main/java/org/mian/gitnex/adapters/MyReposListAdapter.java
#	app/src/main/java/org/mian/gitnex/helpers/StaticGlobalVariables.java
#	app/src/main/res/values/strings.xml

Code Format

Merge branch 'master' into 15-comments-draft

Merge branch 'master' into 15-comments-draft

Merge branch 'master' into 15-comments-draft

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

Go to draft, save on type and other fixes

delete all drafts, added messages where needed

delete draft

Force logout

Merge branch 'master' into 15-comments-draft

Merge branch 'master' into 15-comments-draft

# Conflicts:
#	app/src/main/java/org/mian/gitnex/activities/MainActivity.java
#	app/src/main/java/org/mian/gitnex/helpers/StaticGlobalVariables.java

check if account data is null, we need to log the user out for the 1st time.

Merge branch 'master' into 15-comments-draft

fix repo owner, name sequence

Add comments for test, show drafts list

Add repos to db

Add account to db and other refactors to the code

Merge branch 'master' into 15-comments-draft

Merge branch 'master' into 15-comments-draft

Merge branch 'master' into 15-comments-draft

Merge branch 'master' into 15-comments-draft

# Conflicts:
#	app/build.gradle
#	app/src/main/AndroidManifest.xml

Merge branch 'master' into 15-comments-draft

merge

more queries, added dao repositories, layout update

Added queries in dao

some refactor. added models, dao, entities (accounts, repositories, drafts)

WIP on implementing drafts, introduced Room persistence library for db.

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/139
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-07-04 22:51:55 +02:00
f135508745 Release 3.0.0 rc3 (#570)
Release 3.0.0 rc3

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/570
2020-06-30 21:08:10 +02:00
3e5e94790e Update libs, remove depricated libs (#566)
proper decleration

Merge branch 'update-libs-fix-deps' of codeberg.org:gitnex/GitNex into update-libs-fix-deps

import searchview and other improvements

Merge branch 'master' into update-libs-fix-deps

Update libs, remove depricated libs

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/566
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-06-30 20:59:11 +02:00
62aace4b91 Fix old URLs which do not have a slash at the end. (#568)
Merge branch 'master' into fix-older-urls

Fix old URLs which do not have a slash at the end.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/568
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-30 20:36:24 +02:00
2412245a9f Fixing path issues. (#567)
Fixing path issues.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/567
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-30 20:19:55 +02:00
e872069093 Proper URL parsing, label redesign and other improvements. (#564)
Final improvements.

Fixing reply mention.

Do NOT use "instanceUrlRaw" as of now.

Minor fixes

Merge remote-tracking branch 'remotes/main/master' into login-fix

URL parsing, label and other improvements.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/564
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-30 16:43:27 +02:00
5672208fd0 Adding ability to quote and to copy issue comments. (#562)
Minor fix.

Merge branch 'master' into reply-tools

Merge remote-tracking branch 'opyale/reply-tools' into reply-tools

Changing names.

Merge branch 'master' into reply-tools

Adding ability to cite and to copy issue comments.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Co-authored-by: 6543 <6543@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/562
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-28 19:26:59 +02:00
7379e9945d Fixing bugs of previous pull (#563)
Fixing bugs of previous pull.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/563
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-06-28 18:48:33 +02:00
815417bf11 Refactoring LoginActivity and other improvements. (#561)
Adding error message for login().

Final touch.

Refactoring LoginActivity and other improvements.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/561
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-06-28 17:11:59 +02:00
95fc5e1e9a Fix bug #549, add more file ext to file viewer (#560)
Fix empty release notes bug

Add new sponsor

Fix bug #549, add more file ext to file viewer

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/560
Reviewed-by: opyale <opyale@noreply.codeberg.org>
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-06-28 16:45:39 +02:00
f285d47a0b Fix Crash on closed PRs with deleted Fork (#559)
Fix edge-case DeletedFork of a Pull-Branch

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-26 17:09:18 +02:00
2483968f11 Inverting color of divider too (#553)
Inverting color of divider too

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-06-25 01:27:13 +02:00
d0fde4e791 Adjusting icon color to fit background. (#551)
Adjusting icon color to fit background.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-24 23:02:22 +02:00
c7c2ac2a11 Enhance bottomsheets ui (#550)
Fix name collision in themes

Add space between org and repo name

standard use of dimens

more ui improvements

wip to enhance all bottom sheets

Fix radius and improve the ui

enhance bottom sheet

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-06-24 22:29:58 +02:00
4f79ea0156 Fix Crash when searching issues/pr (#547)
fix in pr and ms fragments

Fix Crash when searching issues/pr

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: 6543 <6543@obermui.de>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-24 17:05:02 +02:00
22943ca9cd Fix user team search crash (#545)
Fix team user search crash

Refactor userName

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-06-23 20:59:23 +02:00
5a10127c1c Calculate ImageContrastColor more precise & some doc nits (#544)
Fixing color bug, updating license headers and CONTRIBUTORS

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-by: 6543 <6543@noreply.codeberg.org>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-23 16:54:27 +02:00
7de29687eb Fixing collaborators bug and some improvements in RepoDetailActivity (#543)
* Minor improvements.

* Fixing collaborators bug and many (performance) improvements in RepoDetailActivity.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-06-22 18:28:08 +02:00
1a95475140 Gitea >= v1.12.0 only need read rights for Colaborators Tab (#542)
show "Add Collaborator" option only if you have the right to do so

gitea >= v1.12.0 only need read rights for Colaborators Tab

Signed-off-by: 6543 <6543@obermui.de>

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-22 17:59:36 +02:00
d2265aecae Fix profile title (#541)
Fix profile
2020-06-22 09:57:21 +02:00
626746be8b Release 3.0.0 rc2 (#539)
release 3.0.0 rc2

Co-authored-by: M M Arif <mmarif@swatian.com>
2020-06-11 15:47:28 +02:00
f21f23c1f0 Refactor FileDiffActivety (#537)
use androidx @NonNull instead of jetbrains @NotNull

Merge branch 'master' into refactor_FileDiffActivity

code format corrections

Merge branch 'master' into refactor_FileDiffActivity

add Unit TESTs for ParseDiff.getFileDiffViewArray

add get methods

make rm/add similar to gitea stats

calc diff stat based on diff itself

rename getFileContents -> toString

fix empty content bug & add comments

format AppUtil.java

rm unused

working version

skip binary files for now ... [DONT CRASH]

better regex

format FileDiffView.java

rename toolbar_title -> toolbarTitle

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-11 15:31:11 +02:00
5005fcc5b5 Redesign releases screen (#526)
Add download assets

implement release layout in adapter

update the layout

Fixing gravity.

Adding layouts for new release items.

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-06-11 01:45:11 +02:00
008e446b93 GitNex drop 1.10 support and add 1.13 (#538)
GitNex drop 1.10 support and add 1.13

rm unused

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-10 17:22:49 +02:00
50e0142f6c Pull Diff View: Use new API if gitea >= 1.13.0 (#536)
right arg order & right instanceUrl

use new API if gitea >= 1.13.0

correct name

format code

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-06-09 15:36:08 +02:00
42640f2d1c Updating gradle. (#535)
Updating gradle.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-08 18:43:57 +02:00
4a8ee2ea96 Improving design of organisation detail page. (#534)
Design changes and updating dependencies.

Small fix.

Adding missing library.

Cleanup.

Improving design of organisation detail page.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-08 08:34:53 +02:00
acc55e3433 Using blurred avatar as background. (#532)
Fixing NullPointerException when image isn't loaded yet.

Display country instead of raw language code.

Minor improvements and contrasting color.

First changes.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-06 22:04:07 +02:00
e267aa5100 Show archived repo message (#530)
Implement archived repo in all adapters

Merge branch 'archive-repo2' into archive-repo

Fix typos

Fixing gravity.

Restoring old names.

Design changes.

Adjusting sizing.

Improving design of archived message.

Show archived repo message and other fixes

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-by: opyale <opyale@noreply.codeberg.org>
2020-06-06 21:41:19 +02:00
5e41469452 Move to CodeBerg (#528)
the rest

move to CodeBerg

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
2020-06-04 17:37:51 +02:00
55473701b8 Improving design of "Show more information" (#527)
Adding comments to editorconfig.

Formatting.

Adding link color attribute.

Minor improvements.

Use dedicated layout for additional information.

Co-authored-by: opyale <opyale@noreply.gitea.io>
Reviewed-by: 6543 <6543@noreply.codeberg.org>
2020-06-04 16:21:23 +02:00
546346ff48 Improving milestones. (#525)
Removing unused strings.

Adding a little bit more space between title and progress bar.

Swapping icons.

Merge remote-tracking branch 'remotes/main/master' into improve-milestones

# Conflicts:
#	app/src/main/res/layout/list_milestones.xml

Minor improvements.

Merge branch 'improve-layouts' of https://gitea.com/opyale/GitNex into improve-milestones

Merge branch 'improve-layouts' of https://gitea.com/gitnex/GitNex into improve-milestones

Moving items.

Merge branch 'master' into improve-layouts

Merge branch 'master' into improve-layouts

Translation and additional formatting.

Enhancing editorconfig

Formatting and removing unused imports.

Removing milestone state.

Improving milestones.

branches and milestones layout update. Fix milestone infinite pagination loop for lower versions

layout updates for issues, pr. Fix pr nullable objects for lower versions

improve files layout

improve org info and list orgs

improve teams list layout by org

Fix repo layouts

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/525
Reviewed-by: M M Arif <mmarif@swatian.com>
2020-06-01 16:43:58 +00:00
4f0091f151 Improve layouts (#524)
make release checkboxes unchecked

admin users layout update

update commits and releases layout

profile fragments layout updates

improve labels

Merge branch 'master' into improve-layouts

branches and milestones layout update. Fix milestone infinite pagination loop for lower versions

layout updates for issues, pr. Fix pr nullable objects for lower versions

improve files layout

improve org info and list orgs

improve teams list layout by org

Fix repo layouts

Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/524
Reviewed-by: opyale <opyale@noreply.gitea.io>
2020-06-01 15:53:56 +00:00
37367e142f Fixes for rc1 (#523)
Fix commits query limit

Fix text colors for auto theme

Fix text color in grid views

fix file size for dir

Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/523
Reviewed-by: opyale <opyale@noreply.gitea.io>
2020-06-01 14:19:34 +00:00
631 changed files with 29537 additions and 15610 deletions

View File

@ -26,6 +26,12 @@ steps:
# depends_on: [ clone ]
# commands:
# - /opt/intellij/bin/idea.sh inspect/format ...
#
# - name: do-or-check-formatting
# image: dlsniper/docker-intellij
# depends_on: [ clone ]
# commands:
# - /opt/intellij/bin/idea.sh format -s .idea/codeStyles/Project.xml -m *.java app/src/main/java
trigger:
event:
@ -60,19 +66,19 @@ steps:
- name: build
image: nextcloudci/android:android-49
commands:
- ./gradlew build
- ./gradlew assembleFreeRelease
- name: sign
image: nextcloudci/android:android-49
environment:
TOKEN:
BOT_TOKEN:
from_secret: BOT_TOKEN
KS_PASS:
from_secret: KS_PASS
KEY_PASS:
from_secret: KEY_PASS
OUTPUT: signed.apk
GITEA: https://gitea.com
INSTANCE: https://codeberg.org
KS_FILE: ci_keystore.jks
KS_REPO:
from_secret: KS_REPO
@ -88,7 +94,7 @@ steps:
PLUGIN_FILE: 'signed.apk'
PLUGIN_TIMEOUT: 180
PLUGIN_ATTEMPTS: 5
PLUGIN_DESTINATION: 'https://cloud.swatian.com/remote.php/dav/files/GitNexBot/GitNex-Builds/latest.apk'
PLUGIN_DESTINATION: 'https://cloud.swatian.com/remote.php/dav/files/GitNexBot/gitnex/builds/latest.apk'
PLUGIN_CUSTOM_ARGUMENTS: '--progress-bar'
trigger:

View File

@ -4,14 +4,22 @@ end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 150
[*.java]
indent_style = tab
max_line_length = 220
line_comment = //
block_comment_start = /*
block_comment = *
block_comment_end = */
[*.json]
indent_size = 2
[{*.yml,*.yaml}]
indent_size = 2
[*.md]
trim_trailing_whitespace = false
insert_final_newline = false

View File

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

View File

@ -1,8 +1,9 @@
Please check the following:
### Describe what your pull request does and which issue youre targeting
<!-- Create a new issue, if it doesn't exist yet -->
<br><br>
1. Make sure you are targeting the `master` branch, pull requests on release branches are only allowed for bug fixes.
2. Read contributing guidelines: [CONTRIBUTING.md](https://gitea.com/GitNex/GitNex/src/branch/master/CONTRIBUTING.md)
3. Please follow the [Code-Standards](https://gitea.com/gitnex/GitNex/wiki/Code-Standards)
4. Describe what your pull request does and which issue youre targeting (create one if does not exist)
<!-- Make sure you are targeting the master branch, pull requests on release branches are only allowed for bug fixes. -->
**You MUST delete the content above including this line before posting, otherwise your pull request will be invalid.**
- [ ] I carefully read the [contribution guidelines](https://codeberg.org/GitNex/GitNex/src/branch/master/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/master/LICENSE).

3
.gitignore vendored
View File

@ -11,6 +11,9 @@
# Release dir
app/release/*
# Pro dir
app/pro/*
# Files for the ART/Dalvik VM
*.dex

69
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,69 @@
stages:
- test
- build
- sign
- publish
test:
image: nextcloudci/android:android-49
stage: test
only:
- master
- tags
script:
- ./gradlew test
build:
image: nextcloudci/android:android-49
stage: build
only:
- master
- tags
script:
- ./gradlew assembleFreeRelease
artifacts:
paths:
- app/build/outputs/
expire_in: 15 minutes
sign:
image: nextcloudci/android:android-49
stage: sign
only:
- master
- tags
variables:
OUTPUT: "signed.apk"
INSTANCE: "https://codeberg.org"
KS_FILE: "ci_keystore.jks"
script:
- ./scripts/sign-build.sh
artifacts:
paths:
- signed.apk
expire_in: 15 minutes
latest:
image: tutum/curl
stage: publish
only:
- master
- tags
variables:
WEBDAV_USERNAME: "GitNexBot"
PLUGIN_FILE: "signed.apk"
PLUGIN_DESTINATION: "https://cloud.swatian.com/remote.php/dav/files/GitNexBot/gitnex/builds/latest.apk"
script:
- curl -T "$PLUGIN_FILE" -u "$WEBDAV_USERNAME":"$WEBDAV_PASSWORD" "$PLUGIN_DESTINATION"
release:
image: tutum/curl
stage: publish
only:
- tags
variables:
WEBDAV_USERNAME: "GitNexBot"
PLUGIN_FILE: "signed.apk"
script:
- "[[ $CI_COMMIT_REF_NAME == *'-rc'* ]] && echo 'Upload blocked. Build seems to be a release candidate.' && exit 0"
- curl -T "$PLUGIN_FILE" -u "$WEBDAV_USERNAME":"$WEBDAV_PASSWORD" 'https://cloud.swatian.com/remote.php/dav/files/GitNexBot/gitnex/releases/'"$CI_COMMIT_REF_NAME"'.apk'

View File

@ -16,6 +16,24 @@
</value>
</option>
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" alias="false" withSubpackages="false" />
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
<package name="io.ktor" alias="false" withSubpackages="true" />
</value>
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
</JetCodeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="RIGHT_MARGIN" value="220" />
<option name="KEEP_LINE_BREAKS" value="false" />
@ -29,6 +47,7 @@
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="FINALLY_ON_NEW_LINE" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
@ -36,8 +55,13 @@
<option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_SYNCHRONIZED_PARENTHESES" value="false" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="TERNARY_OPERATION_WRAP" value="1" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="WRAP_ON_TYPING" value="1" />
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
<option name="SMART_TABS" value="true" />
@ -156,4 +180,4 @@
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>
</component>

View File

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

View File

@ -2,26 +2,35 @@
Please take a few minutes to read this document to make the process of contribution more easy and healthy for all involved.
## Pull Requests
Patches, enhancements, features are always welcome. The PR should focus on the scope of work and avoid many unnecessary commits. Please provide as much detail and context as possible to explain the work submitted.
### General
> **Be polite and gentle while commenting or creating new issues to maintain a healthy environment in which __everyone__ is able to feel comfortable.**
<br>
Please ask if you are not sure about the scope of work to be submitted to avoid waste of time spent on the work.
### Issues and Reports
Before creating an issue please take a moment and search the repository issues(open/closed) to avoid duplicate issues either it's a bug or feature.
In case you want to submit a bug report, please provide as much details as possible to better debug the problem. The important part is how to reproduce the bug and steps to reproduce are appreciated.<br><br>
**Note:** Please contact the project directly via [email](mailto:gitnex@swatian.com) if have to share sensitive and security related details.
<br>
**Code Standards**
### Pull Requests
Patches, enhancements and features are always welcome.
The PR should focus on the scope of work and avoid many unnecessary commits.
Please provide as much detail and context as possible to explain the work submitted.
**Please ask if you are not sure about the scope of work to be submitted to avoid waste of time spent on the work.** (Submit an issue, __before__ submitting a PR)
**Code Standards**<br><br>
Please follow the code standards, this will help other developers to understand your code too.
It also helps maintaining the code afterwards.
It is documented in the Wiki: [Code-Standards](https://gitea.com/gitnex/GitNex/wiki/Code-Standards)
It is documented in the Wiki: [Code-Standards](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards)
**How to submit a PR**
Fork this repository. Pull the forked repository from your namespace to your local machine. Create new branch and work on the bug/feature/enhancement you would like to submit. Push it to your forked version. From there create Pull Request(PR) against **master** branch.
**How to submit a PR (Pull Request)**
1. Fork this repository.
2. Clone the forked repository from your namespace to your local machine.
3. Create a new branch and work on your feature, enhancement or patch.
4. Push your commits to your forked version.
5. You can now create a PR using the web interface against **master** branch.
**IMPORTANT:** By submitting PR, you agree to allow GitNex to license your work under the same license as that used by GitNex.
For more information, click [here](http://makeapullrequest.com/).
## Issues and Reports
*1st of please be polite and gentle while commenting or creating new issue to maintain a healthy environment.*
Before creating an issue please take a moment and search the repository issues(open/closed) to avoid duplicate issues either it's a bug or feature.
In case you want to submit a bug report, please provide as much details as possible to better debug the problem. The important part is how to reproduce the bug and steps to reproduce are appreciated.
**Note:** Please contact the project directly via email(gitnex@swatian.com) if have to share sensitive and security related details.
**IMPORTANT:** By submitting PR, you agree to allow GitNex to license your work under the same license as that used by GitNex.

View File

@ -3,6 +3,7 @@ This part lists all PUBLIC individuals having contributed content to the code.
* M M Arif (mmarif)
* 6543
* opyale
* Unpublished
# Translators

63
LICENSE
View File

@ -1,7 +1,7 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@ -620,55 +620,18 @@ copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
GitNex is an Android client/application for Gitea.
Copyright (C) 2019 The GitNex Authors
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Mastalab is a Mastodon client for Android devices
Copyright (C) 2017 Thomas Schneider
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Mastalab Copyright (C) 2017 Thomas Schneider
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.

View File

@ -1,91 +1,93 @@
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![Release](https://img.shields.io/badge/dynamic/json.svg?label=release&url=https://gitea.com/api/v1/repos/gitnex/GitNex/releases&query=$[0].tag_name)](https://gitea.com/gitnex/GitNex/releases) [![Build Status](https://drone.gitea.com/api/badges/gitnex/GitNex/status.svg)](https://drone.gitea.com/gitnex/GitNex) [![Crowdin](https://badges.crowdin.net/gitnex/localized.svg)](https://crowdin.com/project/gitnex) [![Join the Discord chat at https://discord.gg/FbSS4rf](https://img.shields.io/discord/632219664587685908.svg)](https://discord.gg/FbSS4rf)
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![Pipeline status](https://img.shields.io/gitlab/pipeline/opyale/gitnex/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)
[<img alt="Become a Patroen" src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" height="40"/>](https://www.patreon.com/mmarif) [<img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg" height="40"/>](https://liberapay.com/mmarif/donate)
[<img alt="Become a Patroen" src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" height="40"/>](https://www.patreon.com/mmarif)
# GitNex - Android client for Gitea
GitNex is a free, 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.
## Downloads
[<img alt='Get it on F-droid' src='https://gitlab.com/fdroid/artwork/raw/master/badge/get-it-on.png' height="80"/>](https://f-droid.org/en/packages/org.mian.gitnex/)
[<img alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png' height="80"/>](https://play.google.com/store/apps/details?id=org.mian.gitnex)
[<img alt='Download APK' src='https://gitnex.com/img/download-apk.png' height="80"/>](https://cloud.swatian.com/s/QoDFzMxmnf2FfYw)
Download latest build from master: [https://cloud.swatian.com/s/Cq592xGEfnsGAAW](https://cloud.swatian.com/s/Cq592xGEfnsGAAW)
[<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)
## Note about Gitea version
Please make sure that you are on latest stable release or later for better app experience.
Check the versions [compatibility page](https://gitea.com/gitnex/GitNex/wiki/Compatibility) which lists all the supported versions with compatibility ratio.
Check the versions [compatibility page](https://codeberg.org/gitnex/GitNex/wiki/Compatibility) which lists all the supported versions with compatibility ratio.
## Build from source
Option 1 - Download the source code, open it in Android Studio and build it there.
Option 2 - Open terminal(Linux) and cd to the project dir. Run `./gradlew build`.
Option 2 - Open terminal(Linux) and cd to the project dir. Run `./gradlew assembleFree`.
## Features
- Multiple accounts support
- File and directory browser
- File viewer
- Create files
- Explore repositories
- Issues list
- Pull requests
- Merge pull request
- [MANY MORE](https://gitea.com/gitnex/GitNex/wiki/Features)
- Files diff for PRs
- Notifications
- Drafts
- Repositories / issues / org list
- [MANY MORE](https://codeberg.org/gitnex/GitNex/wiki/Features)
## Contributing
[CONTRIBUTING](https://gitea.com/gitnex/GitNex/src/branch/master/CONTRIBUTING.md)
[CONTRIBUTING](https://codeberg.org/gitnex/GitNex/src/branch/master/CONTRIBUTING.md)
## Translation
Help us translate GitNex to your native language.
We use [Crowdin](https://crowdin.com/project/gitnex) for translation. If your language is not listed, please request [here](https://gitea.com/gitnex/GitNex/issues) to add it to the project.
We use [Crowdin](https://crowdin.com/project/gitnex) for translation. If your language is not listed, please request [here](https://codeberg.org/gitnex/GitNex/issues) to add it to the project.
**Link: https://crowdin.com/project/GitNex**
## Screenshots:
<img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/001.png" alt="001.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/002.png" alt="002.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/003.png" alt="003.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/004.png" alt="004.png" width="200"/>
<img src="https://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://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/005.png" alt="005.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/006.png" alt="006.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/007.png" alt="007.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/008.png" alt="008.png" width="200"/>
<img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/005.png" alt="005.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/006.png" alt="006.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/007.png" alt="007.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/008.png" alt="008.png" width="200"/>
## FAQ
[Faq](https://gitea.com/gitnex/GitNex/wiki/FAQ)
[Faq](https://codeberg.org/gitnex/GitNex/wiki/FAQ)
## Links
[Website](https://gitnex.com)
[Wiki](https://gitea.com/gitnex/GitNex/wiki/Home)
[Wiki](https://codeberg.org/gitnex/GitNex/wiki/Home)
[Website Repository](https://gitlab.com/mmarif4u/gitnex-website)
[Troubleshoot Guide](https://gitea.com/gitnex/GitNex/wiki/Troubleshoot-Guide)
[Troubleshoot Guide](https://codeberg.org/gitnex/GitNex/wiki/Troubleshoot-Guide)
## Thanks
Thanks to all the open source libraries, contributors and donators.
Open source libraries
#### Open source libraries
- Retrofit
- Gson
- Okhttp
- ViHtarb/tooltip
- Picasso
- Markwon
- Prism4j
- Prettytime
- Amulyakhare/textdrawable
- Vdurmont/emoji-java
- Abumoallim/android-multi-select-dialog
- Pes/materialcolorpicker
- Hendraanggrian/socialview
- HamidrezaAmz/BreadcrumbsView
- Chrisbanes/PhotoView
- Pddstudio/highlightjs-android
- Apache/commons-io
- Caverock/androidsvg
- Droidsonroids.gif/android-gif-drawable
- Barteksc/AndroidPdfViewer
- Ge0rg/MemorizingTrustManager
- Barteksc/androidPdfViewer
- Ge0rg/memorizingTrustManager
- Dimezis/blurView
- Mikaelhg/urlbuilder
[Follow me on Fediverse - mastodon.social/@mmarif](https://mastodon.social/@mmarif)

View File

@ -1,17 +1,30 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
compileSdkVersion 30
defaultConfig {
applicationId "org.mian.gitnex"
minSdkVersion 21
targetSdkVersion 29
versionCode 295
versionName "3.0.0-rc1"
targetSdkVersion 30
versionCode 330
versionName "3.3.0"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
viewBinding {
enabled = true
dexOptions {
javaMaxHeapSize "4g"
}
flavorDimensions "default"
productFlavors {
free {
applicationId "org.mian.gitnex"
}
pro {
applicationId "org.mian.gitnex.pro"
}
}
buildFeatures {
viewBinding = true
}
buildTypes {
release {
@ -25,8 +38,13 @@ android {
abortOnError false
}
compileOptions {
targetCompatibility = "8"
sourceCompatibility = "8"
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig{
vectorDrawables.useSupportLibrary = true
}
}
@ -36,29 +54,29 @@ configurations {
}
dependencies {
def lifecycle_version = "2.2.0"
def markwon_version = '4.3.1'
def acra = "5.5.0"
def lifecycle_version = '2.3.0-beta01'
def markwon_version = '4.6.0'
def work_version = "2.4.0"
def acra = "5.7.0"
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "androidx.appcompat:appcompat:1.2.0-rc01"
implementation "com.google.android.material:material:1.2.0-beta01"
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'
implementation 'com.google.android.material:material:1.3.0-alpha03'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.legacy:legacy-support-v4:1.0.0"
testImplementation "junit:junit:4.13"
androidTestImplementation "androidx.test:runner:1.2.0"
androidTestImplementation "androidx.test.espresso:espresso-core:3.2.0"
implementation "com.github.vihtarb:tooltip:0.2.0"
implementation 'com.squareup.okhttp3:okhttp:4.7.0'
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation "com.google.code.gson:gson:2.8.6"
implementation "com.squareup.picasso:picasso:2.71828"
implementation "com.amulyakhare:com.amulyakhare.textdrawable:1.0.1"
implementation 'com.squareup.retrofit2:retrofit:2.8.1'
implementation 'com.squareup.retrofit2:converter-gson:2.8.1'
implementation 'com.squareup.retrofit2:converter-scalars:2.8.1'
implementation 'com.squareup.okhttp3:logging-interceptor:4.7.0'
implementation 'org.ocpsoft.prettytime:prettytime:4.0.5.Final'
implementation "com.vdurmont:emoji-java:5.1.1"
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
implementation 'org.ocpsoft.prettytime:prettytime:4.0.6.Final'
implementation "com.pes.materialcolorpicker:library:1.2.5"
implementation "io.noties.markwon:core:$markwon_version"
implementation "io.noties.markwon:ext-latex:$markwon_version"
@ -73,18 +91,25 @@ dependencies {
implementation "io.noties.markwon:recycler-table:$markwon_version"
implementation "io.noties.markwon:simple-ext:$markwon_version"
implementation "io.noties.markwon:syntax-highlight:$markwon_version"
implementation "io.noties.markwon:image-picasso:$markwon_version"
implementation "io.noties:prism4j: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.19"
implementation "com.hendraanggrian.appcompat:socialview:0.2"
implementation "com.hendraanggrian.appcompat:socialview-commons:0.2"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.21"
implementation "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9"
implementation "commons-io:commons-io:20030203.000550"
implementation 'org.apache.commons:commons-lang3:3.11'
implementation "com.github.chrisbanes:PhotoView:2.3.0"
implementation "com.github.barteksc:android-pdf-viewer:3.2.0-beta.1"
implementation "ch.acra:acra-mail:$acra"
implementation "ch.acra:acra-limiter:$acra"
implementation "ch.acra:acra-notification:$acra"
implementation "androidx.room:room-runtime:2.2.5"
annotationProcessor "androidx.room:room-compiler:2.2.5"
implementation "androidx.work:work-runtime:$work_version"
implementation "com.eightbitlab:blurview:1.6.4"
implementation "io.mikael:urlbuilder:2.0.9"
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.0"
}

View File

@ -4,6 +4,7 @@
package="org.mian.gitnex">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
@ -11,54 +12,81 @@
android:icon="@mipmap/app_logo"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:resizeableActivity="true"
android:roundIcon="@mipmap/app_logo_round"
android:supportsRtl="true"
tools:targetApi="n">
<activity android:name=".activities.MergePullRequestActivity" />
<activity
android:name=".activities.MergePullRequestActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.FileViewActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.CreateFileActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.RepoWatchersActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.RepoStargazersActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".activities.AdminGetUsersActivity" />
<activity
android:name=".activities.AddRemoveAssigneesActivity"
android:theme="@style/Theme.AppCompat.Light.Dialog" />
<activity android:name=".activities.CreateReleaseActivity" />
<activity android:name=".activities.EditIssueActivity" />
<activity android:name=".activities.CreateNewUserActivity" />
android:name=".activities.AdminGetUsersActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AddRemoveLabelsActivity"
android:theme="@style/Theme.AppCompat.Light.Dialog" />
<activity android:name=".activities.ProfileEmailActivity" />
<activity android:name=".activities.AddCollaboratorToRepositoryActivity" />
<activity android:name=".activities.CreateTeamByOrgActivity" />
<activity android:name=".activities.OrganizationTeamMembersActivity" />
android:name=".activities.CreateReleaseActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.EditIssueActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreateNewUserActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.ProfileEmailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AddCollaboratorToRepositoryActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreateTeamByOrgActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.OrganizationTeamMembersActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.OrganizationDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:label="@string/title_activity_org_detail"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".activities.SponsorsActivity" />
<activity android:name=".activities.CreditsActivity" />
<activity android:name=".activities.CreateLabelActivity" />
<activity android:name=".activities.CreateIssueActivity" />
<activity android:name=".activities.CreateMilestoneActivity" />
<activity android:name=".activities.ReplyToIssueActivity" />
<activity
android:name=".activities.CreateLabelActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreateIssueActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreateMilestoneActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.IssueDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustNothing" />
<activity
android:name=".activities.RepoDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:label="@string/title_activity_repo_detail"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".activities.MainActivity" android:theme="@android:style/Theme.NoTitleBar">
<activity
android:name=".activities.MainActivity"
android:theme="@android:style/Theme.NoTitleBar"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -67,19 +95,97 @@
</activity>
<activity
android:name=".activities.LoginActivity"
android:launchMode="singleTask" android:theme="@android:style/Theme.NoTitleBar"/>
<activity android:name=".activities.CreateRepoActivity" />
<activity android:name=".activities.CreateOrganizationActivity" />
<activity android:name=".activities.OpenRepoInBrowserActivity" />
<activity android:name=".activities.FileDiffActivity" />
<activity android:name=".activities.CommitsActivity" />
<activity android:name=".helpers.ssl.MemorizingActivity" android:theme="@android:style/Theme.Material.Dialog" />
<activity android:name=".activities.SettingsAppearanceActivity" />
<activity android:name=".activities.SettingsFileViewerActivity" />
<activity android:name=".activities.SettingsSecurityActivity" />
<activity android:name=".activities.SettingsTranslationActivity" />
<activity android:name=".activities.SettingsReportsActivity" />
<activity android:name=".activities.AddNewTeamMemberActivity" />
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:launchMode="singleTask"
android:theme="@android:style/Theme.NoTitleBar"/>
<activity
android:name=".activities.CreateRepoActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreateOrganizationActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.OpenRepoInBrowserActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.FileDiffActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CommitsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".helpers.ssl.MemorizingActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:theme="@android:style/Theme.Material.Dialog" />
<activity
android:name=".activities.SettingsAppearanceActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsFileViewerActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsSecurityActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsTranslationActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsReportsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AddNewTeamMemberActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsDraftsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.RepoForksActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AddNewAccountActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.RepositorySettingsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreatePullRequestActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsGeneralActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsNotificationsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>
<!-- Version >= 3.0. DeX Dual Mode support -->
<meta-data android:name="com.samsung.android.multidisplay.keep_process_alive" android:value="true"/>
<!-- deep links -->
<activity
android:name=".activities.DeepLinksActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:noHistory="true"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="codeberg.org" />
<data android:host="gitea.com" />
<data android:host="try.gitea.io" />
<data android:host="code.obermui.de" />
<data android:host="git.fsfe.org" />
<data android:host="opendev.org" />
</intent-filter>
</activity>
<!-- deep links -->
</application>
</manifest>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,80 @@
package org.mian.gitnex.actions;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* @author opyale
*/
public class ActionResult<R> {
public enum Status { SUCCESS, FAILED }
private final BlockingQueue<Boolean> blockingQueue;
private final List<OnFinishedListener<R>> onFinishedListeners;
private boolean invalidated = false;
public ActionResult() {
blockingQueue = new ArrayBlockingQueue<>(1);
onFinishedListeners = new ArrayList<>();
}
public void finish(@NonNull Status status) {
finish(status, null);
}
public void finish(@NonNull Status status, R result) {
try {
if(blockingQueue.poll(5, TimeUnit.SECONDS)) {
for(OnFinishedListener<R> onFinishedListener : onFinishedListeners)
onFinishedListener.onFinished(status, result);
}
} catch (InterruptedException ignored) {}
}
public void invalidate() {
if(invalidated) throw new IllegalStateException("Already invalidated");
this.invalidated = true;
}
@SafeVarargs
public synchronized final void accept(@NonNull OnFinishedListener<R>... onFinishedListeners) {
invalidate();
this.blockingQueue.add(true);
this.onFinishedListeners.addAll(Arrays.asList(onFinishedListeners));
}
public synchronized final void discard() {
invalidate();
this.blockingQueue.add(false);
}
public static class None {}
public interface OnFinishedListener<R> {
void onFinished(Status status, R result);
}
}

View File

@ -0,0 +1,118 @@
package org.mian.gitnex.actions;
import android.app.Dialog;
import android.content.Context;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.AssigneesListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class AssigneesActions {
public static void getCurrentIssueAssignees(Context ctx, String repoOwner, String repoName, int issueIndex, List<String> currentAssignees) {
Call<Issues> callSingleIssueLabels = RetrofitClient
.getApiInterface(ctx)
.getIssueByIndex(Authorization.get(ctx), repoOwner, repoName, issueIndex);
callSingleIssueLabels.enqueue(new Callback<Issues>() {
@Override
public void onResponse(@NonNull Call<Issues> call, @NonNull retrofit2.Response<Issues> response) {
if(response.code() == 200) {
Issues issueAssigneesList = response.body();
assert issueAssigneesList != null;
if (issueAssigneesList.getAssignees() != null) {
if(issueAssigneesList.getAssignees().size() > 0) {
for(int i = 0; i < issueAssigneesList.getAssignees().size(); i++) {
currentAssignees.add(issueAssigneesList.getAssignees().get(i).getLogin());
}
}
}
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
public static void getRepositoryAssignees(Context ctx, String repoOwner, String repoName, List<Collaborators> assigneesList, Dialog dialogAssignees, AssigneesListAdapter assigneesAdapter, CustomAssigneesSelectionDialogBinding assigneesBinding) {
TinyDB tinyDB = TinyDB.getInstance(ctx);
Call<List<Collaborators>> call = RetrofitClient
.getApiInterface(ctx)
.getCollaborators(Authorization.get(ctx), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull retrofit2.Response<List<Collaborators>> response) {
assigneesList.clear();
List<Collaborators> assigneesList_ = response.body();
assigneesBinding.progressBar.setVisibility(View.GONE);
assigneesBinding.dialogFrame.setVisibility(View.VISIBLE);
if (response.code() == 200) {
assert assigneesList_ != null;
if(assigneesList_.size() > 0) {
assigneesList.add(new Collaborators(tinyDB.getString("userFullname"), tinyDB.getString("loginUid"), tinyDB.getString("userAvatar")));
assigneesList.addAll(assigneesList_);
}
else {
dialogAssignees.dismiss();
Toasty.warning(ctx, ctx.getResources().getString(R.string.noAssigneesFound));
}
assigneesBinding.assigneesRecyclerView.setAdapter(assigneesAdapter);
}
else {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
}
}

View File

@ -2,18 +2,20 @@ package org.mian.gitnex.actions;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.AddCollaboratorToRepositoryActivity;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Permission;
import org.mian.gitnex.util.TinyDB;
import androidx.annotation.NonNull;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -23,21 +25,16 @@ public class CollaboratorActions {
public static void deleteCollaborator(final Context context, final String searchKeyword, String userName) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<Collaborators> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.deleteCollaborator(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, userName);
Call<Collaborators> call = RetrofitClient
.getApiInterface(context)
.deleteCollaborator(Authorization.get(context), repoOwner, repoName, userName);
call.enqueue(new Callback<Collaborators>() {
@ -47,12 +44,12 @@ public class CollaboratorActions {
if(response.isSuccessful()) {
if(response.code() == 204) {
Toasty.info(context, context.getString(R.string.removeCollaboratorToastText));
Toasty.success(context, context.getString(R.string.removeCollaboratorToastText));
((AddCollaboratorToRepositoryActivity)context).finish();
//Log.i("addCollaboratorSearch", addCollaboratorSearch.getText().toString());
//tinyDb.putBoolean("updateDataSet", true);
//AddCollaboratorToRepositoryActivity usersSearchData = new AddCollaboratorToRepositoryActivity();
//usersSearchData.loadUserSearchList(instanceUrl, instanceToken, searchKeyword, context);
//usersSearchData.loadUserSearchList(instanceToken, searchKeyword, context);
}
}
@ -66,17 +63,17 @@ public class CollaboratorActions {
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
Toasty.warning(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
Toasty.error(context, context.getString(R.string.genericError));
}
@ -92,22 +89,18 @@ public class CollaboratorActions {
public static void addCollaborator(final Context context, String permission, String userName) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Permission permissionString = new Permission(permission);
Call<Permission> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.addCollaborator(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, userName, permissionString);
Call<Permission> call = RetrofitClient
.getApiInterface(context)
.addCollaborator(Authorization.get(context), repoOwner, repoName, userName, permissionString);
call.enqueue(new Callback<Permission>() {
@ -117,10 +110,10 @@ public class CollaboratorActions {
if(response.isSuccessful()) {
if(response.code() == 204) {
Toasty.info(context, context.getString(R.string.addCollaboratorToastText));
Toasty.success(context, context.getString(R.string.addCollaboratorToastText));
((AddCollaboratorToRepositoryActivity)context).finish();
//AddCollaboratorToRepositoryActivity usersSearchData = new AddCollaboratorToRepositoryActivity();
//usersSearchData.loadUserSearchList(instanceUrl, instanceToken, searchKeyword, context);
//usersSearchData.loadUserSearchList(instanceToken, searchKeyword, context);
}
}
@ -134,17 +127,17 @@ public class CollaboratorActions {
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
Toasty.warning(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
Toasty.error(context, context.getString(R.string.genericError));
}
@ -154,8 +147,50 @@ public class CollaboratorActions {
public void onFailure(@NonNull Call<Permission> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
public static ActionResult<List<Collaborators>> getCollaborators(Context context) {
ActionResult<List<Collaborators>> actionResult = new ActionResult<>();
TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getApiInterface(context)
.getCollaborators(Authorization.get(context), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
actionResult.finish(ActionResult.Status.SUCCESS, response.body());
}
else {
actionResult.finish(ActionResult.Status.FAILED);
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
actionResult.finish(ActionResult.Status.FAILED);
}
});
return actionResult;
}
}

View File

@ -1,20 +1,20 @@
package org.mian.gitnex.actions;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.IssueComments;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.UpdateIssueState;
import org.mian.gitnex.util.TinyDB;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -22,83 +22,72 @@ import retrofit2.Callback;
public class IssueActions {
public static void editIssueComment(final Context ctx, final int commentId, final String commentBody) {
public static ActionResult<Response<?>> edit(Context context, String comment, int commentId) {
ActionResult<Response<?>> actionResult = new ActionResult<>();
TinyDB tinyDb = TinyDB.getInstance(context);
final TinyDB tinyDb = new TinyDB(ctx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
IssueComments commentBodyJson = new IssueComments(commentBody);
Call<IssueComments> call;
String repoOwner = parts[0];
String repoName = parts[1];
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().patchIssueComment(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, commentId, commentBodyJson);
Call<IssueComments> call = RetrofitClient
.getApiInterface(context)
.patchIssueComment(Authorization.get(context), repoOwner, repoName, commentId, new IssueComments(comment));
call.enqueue(new Callback<IssueComments>() {
@Override
public void onResponse(@NonNull Call<IssueComments> call, @NonNull retrofit2.Response<IssueComments> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
switch(response.code()) {
tinyDb.putBoolean("commentEdited", true);
Toasty.info(ctx, ctx.getString(R.string.editCommentUpdatedText));
((ReplyToIssueActivity) ctx).finish();
case 200:
actionResult.finish(ActionResult.Status.SUCCESS);
break;
}
}
else if(response.code() == 401) {
case 401:
actionResult.finish(ActionResult.Status.FAILED, response);
AlertDialogs.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle), context.getResources().getString(R.string.alertDialogTokenRevokedMessage), context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle), ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
default:
actionResult.finish(ActionResult.Status.FAILED, response);
break;
}
else if(response.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<IssueComments> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
actionResult.finish(ActionResult.Status.FAILED);
}
});
return actionResult;
}
public static void closeReopenIssue(final Context ctx, final int issueIndex, final String issueState) {
final TinyDB tinyDb = new TinyDB(ctx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final TinyDB tinyDb = TinyDB.getInstance(ctx);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
UpdateIssueState issueStatJson = new UpdateIssueState(issueState);
Call<JsonElement> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().closeReopenIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueStatJson);
call = RetrofitClient
.getApiInterface(ctx)
.closeReopenIssue(Authorization.get(ctx), repoOwner, repoName, issueIndex, issueStatJson);
call.enqueue(new Callback<JsonElement>() {
@ -113,13 +102,13 @@ public class IssueActions {
if(issueState.equals("closed")) {
Toasty.info(ctx, ctx.getString(R.string.issueStateClosed));
Toasty.success(ctx, ctx.getString(R.string.issueStateClosed));
tinyDb.putString("issueState", "closed");
}
else if(issueState.equals("open")) {
Toasty.info(ctx, ctx.getString(R.string.issueStateReopened));
Toasty.success(ctx, ctx.getString(R.string.issueStateReopened));
tinyDb.putString("issueState", "open");
}
@ -133,17 +122,17 @@ public class IssueActions {
}
else if(response.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(ctx, ctx.getString(R.string.genericError));
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
@ -152,7 +141,7 @@ public class IssueActions {
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
@ -160,20 +149,23 @@ public class IssueActions {
public static void subscribe(final Context ctx) {
final TinyDB tinyDB = new TinyDB(ctx);
final TinyDB tinyDB = TinyDB.getInstance(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String[] repoFullName = tinyDB.getString("repoFullName").split("/");
if(repoFullName.length != 2) {
return;
}
final String userLogin = tinyDB.getString("userLogin");
final String token = "token " + tinyDB.getString(tinyDB.getString("loginUid") + "-token");
final int issueNr = Integer.parseInt(tinyDB.getString("issueNumber"));
Call<Void> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().addIssueSubscriber(token, repoFullName[0], repoFullName[1], issueNr, userLogin);
call = RetrofitClient
.getApiInterface(ctx)
.addIssueSubscriber(token, repoFullName[0], repoFullName[1], issueNr, userLogin);
call.enqueue(new Callback<Void>() {
@ -184,14 +176,14 @@ public class IssueActions {
if(response.code() == 201) {
Toasty.info(ctx, ctx.getString(R.string.subscribedSuccessfully));
Toasty.success(ctx, ctx.getString(R.string.subscribedSuccessfully));
tinyDB.putBoolean("issueSubscribed", true);
}
else if(response.code() == 200) {
tinyDB.putBoolean("issueSubscribed", true);
Toasty.info(ctx, ctx.getString(R.string.alreadySubscribed));
Toasty.success(ctx, ctx.getString(R.string.alreadySubscribed));
}
@ -203,7 +195,7 @@ public class IssueActions {
}
else {
Toasty.info(ctx, ctx.getString(R.string.subscribtionError));
Toasty.error(ctx, ctx.getString(R.string.subscriptionError));
}
@ -212,7 +204,7 @@ public class IssueActions {
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Toasty.info(ctx, ctx.getString(R.string.unsubscribedSuccessfully));
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
@ -220,9 +212,8 @@ public class IssueActions {
public static void unsubscribe(final Context ctx) {
final TinyDB tinyDB = new TinyDB(ctx);
final TinyDB tinyDB = TinyDB.getInstance(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String[] repoFullName = tinyDB.getString("repoFullName").split("/");
if(repoFullName.length != 2) {
return;
@ -233,7 +224,7 @@ public class IssueActions {
Call<Void> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().delIssueSubscriber(token, repoFullName[0], repoFullName[1], issueNr, userLogin);
call = RetrofitClient.getApiInterface(ctx).delIssueSubscriber(token, repoFullName[0], repoFullName[1], issueNr, userLogin);
call.enqueue(new Callback<Void>() {
@ -244,14 +235,14 @@ public class IssueActions {
if(response.code() == 201) {
Toasty.info(ctx, ctx.getString(R.string.unsubscribedSuccessfully));
Toasty.success(ctx, ctx.getString(R.string.unsubscribedSuccessfully));
tinyDB.putBoolean("issueSubscribed", false);
}
else if(response.code() == 200) {
tinyDB.putBoolean("issueSubscribed", false);
Toasty.info(ctx, ctx.getString(R.string.alreadyUnsubscribed));
Toasty.success(ctx, ctx.getString(R.string.alreadyUnsubscribed));
}
@ -263,7 +254,7 @@ public class IssueActions {
}
else {
Toasty.info(ctx, ctx.getString(R.string.unsubscribtionError));
Toasty.error(ctx, ctx.getString(R.string.unsubscriptionError));
}
@ -272,9 +263,65 @@ public class IssueActions {
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Toasty.info(ctx, ctx.getString(R.string.unsubscribtionError));
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
}
public static ActionResult<ActionResult.None> reply(Context context, String comment, int issueIndex) {
ActionResult<ActionResult.None> actionResult = new ActionResult<>();
TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
Issues issueComment = new Issues(comment);
Call<Issues> call = RetrofitClient
.getApiInterface(context)
.replyCommentToIssue(Authorization.get(context), repoOwner, repoName, issueIndex, issueComment);
call.enqueue(new Callback<Issues>() {
@Override
public void onResponse(@NonNull Call<Issues> call, @NonNull retrofit2.Response<Issues> response) {
if(response.code() == 201) {
actionResult.finish(ActionResult.Status.SUCCESS);
tinyDb.putBoolean("commentPosted", true);
tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("resumePullRequests", true);
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(context, context.getString(R.string.alertDialogTokenRevokedTitle),
context.getString(R.string.alertDialogTokenRevokedMessage),
context.getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
context.getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
actionResult.finish(ActionResult.Status.FAILED);
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Toasty.error(context, context.getResources().getString(R.string.genericServerResponseError));
}
});
return actionResult;
}
}

View File

@ -0,0 +1,131 @@
package org.mian.gitnex.actions;
import android.app.Dialog;
import android.content.Context;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.LabelsListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Labels;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class LabelsActions {
public static void getCurrentIssueLabels(Context ctx, String repoOwner, String repoName, int issueIndex, List<Integer> currentLabelsIds) {
Call<List<Labels>> callSingleIssueLabels = RetrofitClient
.getApiInterface(ctx)
.getIssueLabels(Authorization.get(ctx), repoOwner, repoName, issueIndex);
callSingleIssueLabels.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> response) {
if(response.code() == 200) {
List<Labels> issueLabelsList = response.body();
assert issueLabelsList != null;
if(issueLabelsList.size() > 0) {
for (int i = 0; i < issueLabelsList.size(); i++) {
currentLabelsIds.add(issueLabelsList.get(i).getId());
}
}
}
}
@Override
public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
public static void getRepositoryLabels(Context ctx, String repoOwner, String repoName, List<Labels> labelsList, Dialog dialogLabels, LabelsListAdapter labelsAdapter, CustomLabelsSelectionDialogBinding labelsBinding) {
Call<List<Labels>> call = RetrofitClient
.getApiInterface(ctx)
.getLabels(Authorization.get(ctx), repoOwner, repoName);
call.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> response) {
labelsList.clear();
if (response.code() == 200) {
if(response.body() != null) {
labelsList.addAll(response.body());
}
// Load organization labels
Call<List<Labels>> callOrgLabels = RetrofitClient
.getApiInterface(ctx)
.getOrganizationLabels(Authorization.get(ctx), repoOwner);
callOrgLabels.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> responseOrg) {
labelsBinding.progressBar.setVisibility(View.GONE);
labelsBinding.dialogFrame.setVisibility(View.VISIBLE);
if(responseOrg.body() != null) {
labelsList.addAll(responseOrg.body());
}
if(labelsList.isEmpty()) {
dialogLabels.dismiss();
Toasty.warning(ctx, ctx.getResources().getString(R.string.noLabelsFound));
}
labelsBinding.labelsRecyclerView.setAdapter(labelsAdapter);
}
@Override public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {}
});
}
else {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
}
}

View File

@ -7,9 +7,9 @@ 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.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.util.TinyDB;
import retrofit2.Call;
import retrofit2.Callback;
@ -23,9 +23,8 @@ public class MilestoneActions {
public static void closeMilestone(final Context ctx, int milestoneId_) {
final TinyDB tinyDB = new TinyDB(ctx);
final TinyDB tinyDB = TinyDB.getInstance(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -37,8 +36,7 @@ public class MilestoneActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.closeReopenMilestone(token, repoOwner, repoName, milestoneId_, milestoneStateJson);
call.enqueue(new Callback<JsonElement>() {
@ -48,7 +46,7 @@ public class MilestoneActions {
if(response.isSuccessful()) {
Toasty.info(ctx, ctx.getString(R.string.milestoneStatusUpdate));
Toasty.success(ctx, ctx.getString(R.string.milestoneStatusUpdate));
}
else if(response.code() == 401) {
@ -61,7 +59,7 @@ public class MilestoneActions {
}
else {
Toasty.info(ctx, ctx.getString(R.string.genericError));
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
@ -81,9 +79,8 @@ public class MilestoneActions {
public static void openMilestone(final Context ctx, int milestoneId_) {
final TinyDB tinyDB = new TinyDB(ctx);
final TinyDB tinyDB = TinyDB.getInstance(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -95,8 +92,7 @@ public class MilestoneActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.closeReopenMilestone(token, repoOwner, repoName, milestoneId_, milestoneStateJson);
call.enqueue(new Callback<JsonElement>() {
@ -106,7 +102,7 @@ public class MilestoneActions {
if(response.isSuccessful()) {
Toasty.info(ctx, ctx.getString(R.string.milestoneStatusUpdate));
Toasty.success(ctx, ctx.getString(R.string.milestoneStatusUpdate));
}
else if(response.code() == 401) {
@ -119,7 +115,7 @@ public class MilestoneActions {
}
else {
Toasty.info(ctx, ctx.getString(R.string.genericError));
Toasty.error(ctx, ctx.getString(R.string.genericError));
}

View File

@ -0,0 +1,57 @@
package org.mian.gitnex.actions;
import android.content.Context;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.NotificationThread;
import java.io.IOException;
import java.util.Date;
import okhttp3.ResponseBody;
import retrofit2.Call;
/**
* Author opyale
*/
public class NotificationsActions {
public enum NotificationStatus {READ, UNREAD, PINNED}
private TinyDB tinyDB;
private Context context;
private String instanceToken;
public NotificationsActions(Context context) {
this.context = context;
this.tinyDB = TinyDB.getInstance(context);
String loginUid = tinyDB.getString("loginUid");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
}
public void setNotificationStatus(NotificationThread notificationThread, NotificationStatus notificationStatus) throws IOException {
Call<ResponseBody> call = RetrofitClient.getApiInterface(context)
.markNotificationThreadAsRead(instanceToken, notificationThread.getId(), notificationStatus.name());
if(!call.execute().isSuccessful()) {
throw new IllegalStateException();
}
}
public boolean setAllNotificationsRead(Date date) throws IOException {
Call<ResponseBody> call = RetrofitClient.getApiInterface(context)
.markNotificationThreadsAsRead(instanceToken, AppUtil.getTimestampFromDate(context, date), true,
new String[]{"unread", "pinned"}, "read");
return call.execute().isSuccessful();
}
}

View File

@ -8,8 +8,8 @@ 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.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
import retrofit2.Call;
import retrofit2.Callback;
@ -21,10 +21,8 @@ public class RepositoryActions {
public static void starRepository(final Context context) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -33,9 +31,8 @@ public class RepositoryActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.starRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(context)
.starRepository(Authorization.get(context), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {
@ -46,7 +43,7 @@ public class RepositoryActions {
if(response.code() == 204) {
tinyDb.putBoolean("repoCreated", true);
Toasty.info(context, context.getString(R.string.starRepositorySuccess));
Toasty.success(context, context.getString(R.string.starRepositorySuccess));
}
}
@ -60,17 +57,17 @@ public class RepositoryActions {
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
Toasty.warning(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
Toasty.error(context, context.getString(R.string.genericError));
}
@ -86,10 +83,8 @@ public class RepositoryActions {
public static void unStarRepository(final Context context) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -98,9 +93,8 @@ public class RepositoryActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.unStarRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(context)
.unStarRepository(Authorization.get(context), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {
@ -111,7 +105,7 @@ public class RepositoryActions {
if(response.code() == 204) {
tinyDb.putBoolean("repoCreated", true);
Toasty.info(context, context.getString(R.string.unStarRepositorySuccess));
Toasty.success(context, context.getString(R.string.unStarRepositorySuccess));
}
}
@ -125,17 +119,17 @@ public class RepositoryActions {
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
Toasty.warning(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
Toasty.error(context, context.getString(R.string.genericError));
}
@ -151,10 +145,8 @@ public class RepositoryActions {
public static void watchRepository(final Context context) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -163,9 +155,8 @@ public class RepositoryActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.watchRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(context)
.watchRepository(Authorization.get(context), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {
@ -176,7 +167,7 @@ public class RepositoryActions {
if(response.code() == 200) {
tinyDb.putBoolean("repoCreated", true);
Toasty.info(context, context.getString(R.string.watchRepositorySuccess));
Toasty.success(context, context.getString(R.string.watchRepositorySuccess));
}
}
@ -190,17 +181,17 @@ public class RepositoryActions {
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
Toasty.warning(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
Toasty.error(context, context.getString(R.string.genericError));
}
@ -216,10 +207,8 @@ public class RepositoryActions {
public static void unWatchRepository(final Context context) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final TinyDB tinyDb = TinyDB.getInstance(context);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
@ -228,9 +217,8 @@ public class RepositoryActions {
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.unWatchRepository(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(context)
.unWatchRepository(Authorization.get(context), repoOwner, repoName);
call.enqueue(new Callback<JsonElement>() {
@ -240,7 +228,7 @@ public class RepositoryActions {
if(response.code() == 204) {
tinyDb.putBoolean("repoCreated", true);
Toasty.info(context, context.getString(R.string.unWatchRepositorySuccess));
Toasty.success(context, context.getString(R.string.unWatchRepositorySuccess));
}
else if(response.code() == 401) {
@ -253,17 +241,17 @@ public class RepositoryActions {
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
Toasty.warning(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
Toasty.error(context, context.getString(R.string.genericError));
}

View File

@ -8,8 +8,8 @@ import org.mian.gitnex.activities.AddNewTeamMemberActivity;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
import retrofit2.Call;
import retrofit2.Callback;
@ -21,17 +21,13 @@ public class TeamActions {
public static void removeTeamMember(final Context context, String userName, int teamId) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final TinyDB tinyDb = TinyDB.getInstance(context);
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.removeTeamMember(Authorization.returnAuthentication(context, loginUid, instanceToken), teamId, userName);
.getApiInterface(context)
.removeTeamMember(Authorization.get(context), teamId, userName);
call.enqueue(new Callback<JsonElement>() {
@ -43,7 +39,7 @@ public class TeamActions {
if(response.code() == 204) {
tinyDb.putBoolean("teamActionFlag", true);
Toasty.info(context, context.getString(R.string.memberRemovedMessage));
Toasty.success(context, context.getString(R.string.memberRemovedMessage));
((AddNewTeamMemberActivity)context).finish();
}
@ -59,17 +55,17 @@ public class TeamActions {
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
Toasty.warning(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
Toasty.error(context, context.getString(R.string.genericError));
}
@ -87,17 +83,11 @@ public class TeamActions {
public static void addTeamMember(final Context context, String userName, int teamId) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final TinyDB tinyDb = TinyDB.getInstance(context);
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.addTeamMember(Authorization.returnAuthentication(context, loginUid, instanceToken), teamId, userName);
Call<JsonElement> call = RetrofitClient
.getApiInterface(context)
.addTeamMember(Authorization.get(context), teamId, userName);
call.enqueue(new Callback<JsonElement>() {
@ -109,7 +99,7 @@ public class TeamActions {
if(response.code() == 204) {
tinyDb.putBoolean("teamActionFlag", true);
Toasty.info(context, context.getString(R.string.memberAddedMessage));
Toasty.success(context, context.getString(R.string.memberAddedMessage));
((AddNewTeamMemberActivity)context).finish();
}
@ -125,17 +115,17 @@ public class TeamActions {
}
else if(response.code() == 403) {
Toasty.info(context, context.getString(R.string.authorizeError));
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(context, context.getString(R.string.apiNotFound));
Toasty.warning(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.info(context, context.getString(R.string.genericError));
Toasty.error(context, context.getString(R.string.genericError));
}

View File

@ -1,30 +1,28 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.UserSearchAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserSearch;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.models.UserSearch;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -33,8 +31,6 @@ import java.util.List;
public class AddCollaboratorToRepositoryActivity extends BaseActivity {
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private TextView addCollaboratorSearch;
private TextView noData;
private ProgressBar mProgressBar;
@ -50,21 +46,13 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
addCollaboratorSearch = findViewById(R.id.addCollaboratorSearch);
mRecyclerView = findViewById(R.id.recyclerViewUserSearch);
mProgressBar = findViewById(R.id.progress_bar);
mProgressBar = findViewById(R.id.progressBar);
noData = findViewById(R.id.noData);
addCollaboratorSearch.requestFocus();
@ -77,8 +65,11 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
addCollaboratorSearch.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_SEND) {
if(!addCollaboratorSearch.getText().toString().equals("")) {
loadUserSearchList(instanceUrl, instanceToken, addCollaboratorSearch.getText().toString(), loginUid);
mProgressBar.setVisibility(View.VISIBLE);
loadUserSearchList(addCollaboratorSearch.getText().toString());
}
}
@ -88,22 +79,26 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
}
public void loadUserSearchList(String instanceUrl, String token, String searchKeyword, String loginUid) {
public void loadUserSearchList(String searchKeyword) {
Call<UserSearch> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getUserBySearch(Authorization.returnAuthentication(ctx, loginUid, token), searchKeyword, 10);
.getApiInterface(appCtx)
.getUserBySearch(Authorization.get(ctx), searchKeyword, 10);
call.enqueue(new Callback<UserSearch>() {
@Override
public void onResponse(@NonNull Call<UserSearch> call, @NonNull Response<UserSearch> response) {
if (response.isSuccessful()) {
mProgressBar.setVisibility(View.GONE);
if (response.code() == 200) {
assert response.body() != null;
getUsersList(response.body().getData(), ctx);
} else {
}
else {
Log.i("onResponse", String.valueOf(response.code()));
}
@ -130,20 +125,20 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
mProgressBar.setVisibility(View.VISIBLE);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noData.setVisibility(View.GONE);
mProgressBar.setVisibility(View.GONE);
}
else {
noData.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
mProgressBar.setVisibility(View.GONE);
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -0,0 +1,258 @@
package org.mian.gitnex.activities;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.databinding.ActivityAddNewAccountBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.PathsHelper;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.models.UserInfo;
import java.net.URI;
import io.mikael.urlbuilder.UrlBuilder;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class AddNewAccountActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private ActivityAddNewAccountBinding viewBinding;
private enum Protocol {HTTPS, HTTP}
private String spinnerSelectedValue;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_add_new_account;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewBinding = ActivityAddNewAccountBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
initCloseListener();
viewBinding.close.setOnClickListener(onClickListener);
ArrayAdapter<Protocol> adapterProtocols = new ArrayAdapter<>(ctx, R.layout.list_spinner_items, Protocol.values());
viewBinding.protocolSpinner.setAdapter(adapterProtocols);
viewBinding.protocolSpinner.setOnItemClickListener((parent, view1, position, id) -> spinnerSelectedValue = String.valueOf(parent.getItemAtPosition(position)));
viewBinding.addNewAccount.setOnClickListener(login -> {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
}
else {
processLogin();
}
});
}
private void processLogin() {
try {
String instanceUrlET = String.valueOf(viewBinding.instanceUrl.getText());
String loginToken = String.valueOf(viewBinding.loginToken.getText());
String protocol = spinnerSelectedValue;
if(protocol == null) {
Toasty.error(ctx, getResources().getString(R.string.protocolEmptyError));
return;
}
if(instanceUrlET.equals("")) {
Toasty.error(ctx, getResources().getString(R.string.emptyFieldURL));
return;
}
if(loginToken.equals("")) {
Toasty.error(ctx, getResources().getString(R.string.loginTokenError));
return;
}
URI rawInstanceUrl = UrlBuilder.fromString(UrlHelper.fixScheme(instanceUrlET, "http")).toUri();
URI instanceUrl = UrlBuilder.fromUri(rawInstanceUrl).withScheme(protocol.toLowerCase()).withPath(PathsHelper.join(rawInstanceUrl.getPath(), "/api/v1/"))
.toUri();
versionCheck(instanceUrl.toString(), loginToken);
}
catch(Exception e) {
Log.e("onFailure-login", e.toString());
Toasty.error(ctx, getResources().getString(R.string.malformedUrl));
}
}
private void versionCheck(final String instanceUrl, final String loginToken) {
Call<GiteaVersion> callVersion;
callVersion = RetrofitClient.getApiInterface(ctx).getGiteaVersionWithToken("token " + loginToken);
callVersion.enqueue(new Callback<GiteaVersion>() {
@Override
public void onResponse(@NonNull final Call<GiteaVersion> callVersion, @NonNull retrofit2.Response<GiteaVersion> responseVersion) {
if(responseVersion.code() == 200) {
GiteaVersion version = responseVersion.body();
assert version != null;
if(!Version.valid(version.getVersion())) {
Toasty.error(ctx, getResources().getString(R.string.versionUnknown));
return;
}
tinyDB.putString("giteaVersion", version.getVersion());
Version giteaVersion = new Version(version.getVersion());
if(giteaVersion.less(getString(R.string.versionLow))) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(ctx).setTitle(getString(R.string.versionAlertDialogHeader))
.setMessage(getResources().getString(R.string.versionUnsupportedOld, version.getVersion())).setIcon(R.drawable.ic_warning)
.setCancelable(true);
alertDialogBuilder.setNegativeButton(getString(R.string.cancelButton), (dialog, which) -> {
dialog.dismiss();
});
alertDialogBuilder.setPositiveButton(getString(R.string.textContinue), (dialog, which) -> {
dialog.dismiss();
login(instanceUrl, loginToken);
});
alertDialogBuilder.create().show();
}
else if(giteaVersion.lessOrEqual(getString(R.string.versionHigh))) {
login(instanceUrl, loginToken);
}
else {
Toasty.warning(ctx, getResources().getString(R.string.versionUnsupportedNew));
login(instanceUrl, loginToken);
}
}
else if(responseVersion.code() == 403) {
login(instanceUrl, loginToken);
}
}
private void login(String instanceUrl, String loginToken) {
setupNewAccountWithToken(instanceUrl, loginToken);
}
@Override
public void onFailure(@NonNull Call<GiteaVersion> callVersion, @NonNull Throwable t) {
Log.e("onFailure-versionCheck", t.toString());
Toasty.error(ctx, getResources().getString(R.string.errorOnLogin));
}
});
}
private void setupNewAccountWithToken(String instanceUrl, final String loginToken) {
Call<UserInfo> call = RetrofitClient.getApiInterface(ctx, instanceUrl).getUserInfo("token " + loginToken);
call.enqueue(new Callback<UserInfo>() {
@Override
public void onResponse(@NonNull Call<UserInfo> call, @NonNull retrofit2.Response<UserInfo> response) {
UserInfo userDetails = response.body();
switch(response.code()) {
case 200:
assert userDetails != null;
// insert new account to db if does not exist
String accountName = userDetails.getUsername() + "@" + instanceUrl;
UserAccountsApi userAccountsApi = new UserAccountsApi(ctx);
int checkAccount = userAccountsApi.getCount(accountName);
if(checkAccount == 0) {
userAccountsApi.insertNewAccount(accountName, instanceUrl, userDetails.getUsername(), loginToken, "");
Toasty.success(ctx, getResources().getString(R.string.accountAddedMessage));
finish();
}
else {
Toasty.warning(ctx, getResources().getString(R.string.accountAlreadyExistsError));
}
break;
case 401:
Toasty.error(ctx, getResources().getString(R.string.unauthorizedApiError));
break;
default:
Toasty.error(ctx, getResources().getString(R.string.genericApiStatusError) + response.code());
}
}
@Override
public void onFailure(@NonNull Call<UserInfo> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
Toasty.error(ctx, getResources().getString(R.string.genericError));
}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -20,7 +20,6 @@ import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.models.UserSearch;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@ -28,11 +27,13 @@ import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class AddNewTeamMemberActivity extends BaseActivity {
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private TextView addNewTeamMember;
private TextView noData;
private ProgressBar mProgressBar;
@ -52,19 +53,11 @@ public class AddNewTeamMemberActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
addNewTeamMember = findViewById(R.id.addNewTeamMeber);
addNewTeamMember = findViewById(R.id.addNewTeamMember);
mRecyclerView = findViewById(R.id.recyclerViewUserSearch);
mProgressBar = findViewById(R.id.progress_bar);
noData = findViewById(R.id.noData);
@ -77,9 +70,11 @@ public class AddNewTeamMemberActivity extends BaseActivity {
closeActivity.setOnClickListener(onClickListener);
if(getIntent().getStringExtra("teamId") != null && !Objects.requireNonNull(getIntent().getStringExtra("teamId")).equals("")) {
teamId = getIntent().getStringExtra("teamId");
}
else {
teamId = "0";
}
@ -96,13 +91,11 @@ public class AddNewTeamMemberActivity extends BaseActivity {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(!addNewTeamMember.getText().toString().equals("")) {
if(!addNewTeamMember.getText().toString().equals("") && addNewTeamMember.getText().toString().length() > 1) {
adapter = new UserSearchForTeamMemberAdapter(dataList, ctx, Integer.parseInt(teamId));
loadUserSearchList(instanceUrl, instanceToken, addNewTeamMember.getText().toString(), loginUid, teamId);
loadUserSearchList(addNewTeamMember.getText().toString(), teamId);
}
}
@Override
@ -117,9 +110,11 @@ public class AddNewTeamMemberActivity extends BaseActivity {
}
public void loadUserSearchList(String instanceUrl, String token, String searchKeyword, String loginUid, String teamId) {
public void loadUserSearchList(String searchKeyword, String teamId) {
Call<UserSearch> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserBySearch(Authorization.returnAuthentication(ctx, loginUid, token), searchKeyword, 10);
Call<UserSearch> call = RetrofitClient.getApiInterface(ctx).getUserBySearch(Authorization.get(ctx), searchKeyword, 10);
mProgressBar.setVisibility(View.VISIBLE);
call.enqueue(new Callback<UserSearch>() {
@ -135,16 +130,13 @@ public class AddNewTeamMemberActivity extends BaseActivity {
dataList.addAll(response.body().getData());
mRecyclerView.setAdapter(adapter);
noData.setVisibility(View.GONE);
mProgressBar.setVisibility(View.GONE);
}
else {
noData.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
mProgressBar.setVisibility(View.GONE);
}
}

View File

@ -1,294 +0,0 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
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.MultiSelectDialog;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.MultiSelectModel;
import org.mian.gitnex.models.UpdateIssueAssignees;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class AddRemoveAssigneesActivity extends BaseActivity {
private ArrayList<MultiSelectModel> listOfCollaborators = new ArrayList<>();
private ArrayList<Integer> issueAssigneesIds = new ArrayList<>();
private Boolean assigneesFlag = false;
private MultiSelectDialog multiSelectDialogAssignees;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_add_remove_assignees;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
//supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
getAssignees(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
}
private void getAssignees(final String instanceUrl, final String instanceToken, final String repoOwner, final String repoName, final int issueIndex, final String loginUid) {
final TinyDB tinyDb = new TinyDB(appCtx);
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull final Call<List<Collaborators>> call, @NonNull final retrofit2.Response<List<Collaborators>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
final List<Collaborators> collaboratorsList_ = response.body();
assert collaboratorsList_ != null;
if(collaboratorsList_.size() > 0) {
for (int i = 0; i < collaboratorsList_.size(); i++) {
listOfCollaborators.add(new MultiSelectModel(collaboratorsList_.get(i).getId(), collaboratorsList_.get(i).getUsername().trim()));
}
}
// get current issue assignees
Call<Issues> callSingleIssueAssignees = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex);
callSingleIssueAssignees.enqueue(new Callback<Issues>() {
@Override
public void onResponse(@NonNull Call<Issues> call, @NonNull retrofit2.Response<Issues> response) {
if(response.code() == 200) {
Issues issueAssigneesList = response.body();
assert issueAssigneesList != null;
if (issueAssigneesList.getAssignees() != null) {
if (issueAssigneesList.getAssignees().size() > 0) {
for (int i = 0; i < issueAssigneesList.getAssignees().size(); i++) {
issueAssigneesIds.add(issueAssigneesList.getAssignees().get(i).getId());
if(issueAssigneesList.getAssignees().get(i).getUsername().equals(loginUid)) {
listOfCollaborators.add(new MultiSelectModel(issueAssigneesList.getAssignees().get(i).getId(), issueAssigneesList.getAssignees().get(i).getUsername().trim()));
}
}
assigneesFlag = true;
}
}
else {
listOfCollaborators.add(new MultiSelectModel(tinyDb.getInt("userId"), loginUid));
}
if(assigneesFlag) {
multiSelectDialogAssignees = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectAssigneesListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.saveButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.preSelectIDsList(issueAssigneesIds)
.setMaxSelectionLimit(listOfCollaborators.size())
.multiSelectList(listOfCollaborators)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
Log.i("selectedNames", String.valueOf(selectedNames));
updateIssueAssignees(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, loginUid, issueIndex, selectedNames);
tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity();
}
@Override
public void onCancel() {
CloseActivity();
}
});
}
else {
multiSelectDialogAssignees = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectAssigneesListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.saveButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.setMaxSelectionLimit(listOfCollaborators.size())
.multiSelectList(listOfCollaborators)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
updateIssueAssignees(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, loginUid, issueIndex, selectedNames);
tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity();
}
@Override
public void onCancel() {
CloseActivity();
}
});
}
multiSelectDialogAssignees.show(getSupportFragmentManager(), "issueMultiSelectDialog");
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
// get current issue assignees
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(ctx, getString(R.string.genericError));
}
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void CloseActivity() {
this.finish();
}
private void updateIssueAssignees(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String loginUid, int issueIndex, List<String> issueAssigneesList) {
UpdateIssueAssignees updateAssigneeJson = new UpdateIssueAssignees(issueAssigneesList);
Call<JsonElement> call3;
call3 = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.patchIssueAssignees(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, updateAssigneeJson);
call3.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response2) {
if(response2.code() == 201) {
Toasty.info(ctx, ctx.getString(R.string.assigneesUpdated));
}
else if(response2.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(response2.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response2.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
}

View File

@ -1,308 +0,0 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
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.MultiSelectDialog;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.MultiSelectModel;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
/**
* Author M M Arif
*/
public class AddRemoveLabelsActivity extends BaseActivity {
private ArrayList<MultiSelectModel> listOfLabels = new ArrayList<>();
private ArrayList<Integer> issueLabelIds = new ArrayList<>();
private Boolean labelsFlag = false;
private MultiSelectDialog multiSelectDialogLabels;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_add_remove_labels;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
//supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
getLabels(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
}
private void getLabels(final String instanceUrl, final String instanceToken, final String repoOwner, final String repoName, final int issueIndex, final String loginUid) {
final TinyDB tinyDb = new TinyDB(appCtx);
Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getlabels(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Labels> labelsList_ = response.body();
assert labelsList_ != null;
if(labelsList_.size() > 0) {
for (int i = 0; i < labelsList_.size(); i++) {
listOfLabels.add(new MultiSelectModel(labelsList_.get(i).getId(), labelsList_.get(i).getName().trim()));
}
}
// get current issue labels
Call<List<Labels>> callSingleIssueLabels = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getIssueLabels(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex);
callSingleIssueLabels.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> response) {
if(response.code() == 200) {
List<Labels> issueLabelsList = response.body();
assert issueLabelsList != null;
if(issueLabelsList.size() > 0) {
for (int i = 0; i < issueLabelsList.size(); i++) {
issueLabelIds.add(issueLabelsList.get(i).getId());
}
labelsFlag = true;
}
if(labelsFlag) {
multiSelectDialogLabels = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectLabelsListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.saveButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.preSelectIDsList(issueLabelIds)
.setMaxSelectionLimit(listOfLabels.size())
.multiSelectList(listOfLabels)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
String labelIds = selectedIds.toString();
int[] integers;
if (selectedIds.size() > 0) {
String[] items = labelIds.replaceAll("\\[", "").replaceAll("\\]", "").replaceAll("\\s", "").split(",");
integers = new int[items.length];
for (int i = 0; i < integers.length; i++) {
integers[i] = Integer.parseInt(items[i]);
}
}
else {
integers = new int[0];
}
updateIssueLabels(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, integers, loginUid);
tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity();
}
@Override
public void onCancel() {
CloseActivity();
}
});
}
else {
multiSelectDialogLabels = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectLabelsListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.saveButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.setMaxSelectionLimit(listOfLabels.size())
.multiSelectList(listOfLabels)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
String labelIds = selectedIds.toString();
int[] integers;
if (selectedIds.size() > 0) {
String[] items = labelIds.replaceAll("\\[", "").replaceAll("\\]", "").replaceAll("\\s", "").split(",");
integers = new int[items.length];
for (int i = 0; i < integers.length; i++) {
integers[i] = Integer.parseInt(items[i]);
}
}
else {
integers = new int[0];
}
updateIssueLabels(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, integers, loginUid);
tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity();
}
@Override
public void onCancel() {
CloseActivity();
}
});
}
multiSelectDialogLabels.show(getSupportFragmentManager(), "issueMultiSelectDialog");
}
}
@Override
public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
// get current issue labels
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(ctx, getString(R.string.genericError));
}
}
}
@Override
public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void updateIssueLabels(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, int issueIndex, int[] issueLabels, String loginUid) {
Labels patchIssueLabels = new Labels(issueLabels);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.updateIssueLabels(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, patchIssueLabels);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 200) {
Toasty.info(ctx, ctx.getString(R.string.labelsUpdated));
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void CloseActivity() {
this.finish();
}
}

View File

@ -1,17 +1,10 @@
package org.mian.gitnex.activities;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@ -19,16 +12,19 @@ import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.AdminGetUsersAdapter;
import org.mian.gitnex.fragments.BottomSheetAdminUsersFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.AdminGetUsersViewModel;
import java.util.List;
import java.util.Objects;
/**
* Author M M Arif
@ -37,8 +33,6 @@ import java.util.Objects;
public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAdminUsersFragment.BottomSheetListener {
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private AdminGetUsersAdapter adapter;
private RecyclerView mRecyclerView;
private TextView noDataUsers;
@ -53,12 +47,6 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
noDataUsers = findViewById(R.id.noDataUsers);
@ -79,44 +67,37 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
AdminGetUsersViewModel.loadUsersList(ctx, instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken));
}
}, 500);
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
fetchDataAsync(ctx, instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken));
swipeRefresh.setRefreshing(false);
AdminGetUsersViewModel.loadUsersList(ctx, Authorization.get(ctx));
}, 500));
fetchDataAsync(ctx, Authorization.get(ctx));
}
private void fetchDataAsync(Context ctx, String instanceUrl, String instanceToken) {
private void fetchDataAsync(Context ctx, String instanceToken) {
AdminGetUsersViewModel usersModel = ViewModelProviders.of(this).get(AdminGetUsersViewModel.class);
AdminGetUsersViewModel usersModel = new ViewModelProvider(this).get(AdminGetUsersViewModel.class);
usersModel.getUsersList(ctx, instanceUrl, instanceToken).observe(this, new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> usersListMain) {
adapter = new AdminGetUsersAdapter(ctx, usersListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setVisibility(View.VISIBLE);
mRecyclerView.setAdapter(adapter);
noDataUsers.setVisibility(View.GONE);
searchFilter = true;
}
else {
//adapter.notifyDataSetChanged();
//mRecyclerView.setAdapter(adapter);
mRecyclerView.setVisibility(View.GONE);
noDataUsers.setVisibility(View.VISIBLE);
}
usersModel.getUsersList(ctx, instanceToken).observe(this, usersListMain -> {
adapter = new AdminGetUsersAdapter(ctx, usersListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setVisibility(View.VISIBLE);
mRecyclerView.setAdapter(adapter);
noDataUsers.setVisibility(View.GONE);
searchFilter = true;
}
else {
mRecyclerView.setVisibility(View.GONE);
noDataUsers.setVisibility(View.VISIBLE);
}
});
}
@ -127,37 +108,37 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
final MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if(searchFilter) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
if(searchFilter) {
inflater.inflate(R.menu.search_menu, menu);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
inflater.inflate(R.menu.search_menu, menu);
if(!connToInternet) {
return;
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
if(!connToInternet) {
return;
}
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) { return true; }
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
}
});
}
}, 500);
return true;
@ -168,18 +149,21 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
int id = item.getItemId();
switch (id) {
case android.R.id.home:
finish();
return true;
case R.id.genericMenu:
BottomSheetAdminUsersFragment bottomSheet = new BottomSheetAdminUsersFragment();
bottomSheet.show(getSupportFragmentManager(), "usersBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
if(id == android.R.id.home) {
finish();
return true;
}
else if(id == R.id.genericMenu) {
BottomSheetAdminUsersFragment bottomSheet = new BottomSheetAdminUsersFragment();
bottomSheet.show(getSupportFragmentManager(), "usersBottomSheet");
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
@Override
@ -194,12 +178,7 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
}

View File

@ -1,64 +1,98 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import org.acra.ACRA;
import org.acra.BuildConfig;
import org.acra.annotation.AcraCore;
import org.acra.annotation.AcraNotification;
import org.acra.config.CoreConfigurationBuilder;
import org.acra.config.LimiterConfigurationBuilder;
import org.acra.config.MailSenderConfigurationBuilder;
import org.acra.data.StringFormat;
import org.mian.gitnex.R;
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.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.notifications.NotificationsMaster;
import static org.acra.ReportField.ANDROID_VERSION;
import static org.acra.ReportField.PHONE_MODEL;
import static org.acra.ReportField.STACK_TRACE;
/**
* 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 {
protected TinyDB tinyDB;
protected Context ctx = this;
protected Context appCtx;
@Override
public void onCreate(Bundle savedInstanceState) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
this.appCtx = getApplicationContext();
this.tinyDB = TinyDB.getInstance(appCtx);
switch(tinyDb.getInt("themeId")) {
switch(tinyDB.getInt("themeId")) {
case 1:
tinyDB.putString("currentTheme", "light");
setTheme(R.style.AppThemeLight);
break;
case 2:
if(TimeHelper.timeBetweenHours(18, 6)) { // 6pm to 6am
tinyDB.putString("currentTheme", "dark");
setTheme(R.style.AppTheme);
}
else {
} else {
tinyDB.putString("currentTheme", "light");
setTheme(R.style.AppThemeLight);
}
break;
default:
setTheme(R.style.AppTheme);
case 3:
tinyDB.putString("currentTheme", "light");
setTheme(R.style.AppThemeRetro);
break;
case 4:
if(TimeHelper.timeBetweenHours(18, 6)) { // 6pm to 6am
tinyDB.putString("currentTheme", "dark");
setTheme(R.style.AppTheme);
} else {
tinyDB.putString("currentTheme", "light");
setTheme(R.style.AppThemeRetro);
}
break;
default:
tinyDB.putString("currentTheme", "dark");
setTheme(R.style.AppTheme);
}
String appLocale = tinyDb.getString("locale");
String appLocale = tinyDB.getString("locale");
AppUtil.setAppLocale(getResources(), appLocale);
super.onCreate(savedInstanceState);
setContentView(getLayoutResourceId());
switch(tinyDb.getInt("customFontId", -1)) {
// FIXME Performance nightmare
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
FontsOverride.setDefaultFont(this, "DEFAULT", "fonts/roboto.ttf");
@ -79,40 +113,57 @@ public abstract class BaseActivity extends AppCompatActivity {
FontsOverride.setDefaultFont(this, "MONOSPACE", "fonts/manroperegular.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "fonts/manroperegular.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "fonts/manroperegular.ttf");
break;
}
// enabling counter badges by default
if(tinyDb.getString("enableCounterBadgesInit").isEmpty()) {
tinyDb.putBoolean("enableCounterBadges", true);
tinyDb.putString("enableCounterBadgesInit", "yes");
}
if(tinyDB.getInt("pollingDelayMinutes", 0) <= 0) {
tinyDB.putInt("pollingDelayMinutes", StaticGlobalVariables.defaultPollingDelay);
}
// FIXME Performance nightmare
NotificationsMaster.hireWorker(appCtx);
// enabling counter badges by default
if(tinyDB.getString("enableCounterBadgesInit").isEmpty()) {
tinyDB.putBoolean("enableCounterBadges", true);
tinyDB.putString("enableCounterBadgesInit", "yes");
}
// enable crash reports by default
if(tinyDb.getString("crashReportingEnabledInit").isEmpty()) {
tinyDb.putBoolean("crashReportingEnabled", true);
tinyDb.putString("crashReportingEnabledInit", "yes");
if(tinyDB.getString("crashReportingEnabledInit").isEmpty()) {
tinyDB.putBoolean("crashReportingEnabled", true);
tinyDB.putString("crashReportingEnabledInit", "yes");
}
// default cache setter
if(tinyDb.getString("cacheSizeStr").isEmpty()) {
tinyDb.putString("cacheSizeStr", getResources().getString(R.string.cacheSizeDataSelectionSelectedText));
if(tinyDB.getString("cacheSizeStr").isEmpty()) {
tinyDB.putString("cacheSizeStr", getResources().getString(R.string.cacheSizeDataSelectionSelectedText));
}
if(tinyDb.getString("cacheSizeImagesStr").isEmpty()) {
tinyDb.putString("cacheSizeImagesStr", getResources().getString(R.string.cacheSizeImagesSelectionSelectedText));
if(tinyDB.getString("cacheSizeImagesStr").isEmpty()) {
tinyDB.putString("cacheSizeImagesStr", getResources().getString(R.string.cacheSizeImagesSelectionSelectedText));
}
if (tinyDb.getBoolean("crashReportingEnabled")) {
// 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();

View File

@ -1,8 +1,8 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Menu;
@ -20,14 +20,12 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.CommitsAdapter;
import org.mian.gitnex.clients.AppApiService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.interfaces.ApiInterface;
import org.mian.gitnex.models.Commits;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
@ -40,8 +38,6 @@ import retrofit2.Response;
public class CommitsActivity extends BaseActivity {
final Context ctx = this;
private Context appCtx;
private View.OnClickListener onClickListener;
private TextView noData;
private ProgressBar progressBar;
@ -52,7 +48,7 @@ public class CommitsActivity extends BaseActivity {
private RecyclerView recyclerView;
private List<Commits> commitsList;
private CommitsAdapter adapter;
private ApiInterface api;
private ProgressBar progressLoadMore;
@Override
protected int getLayoutResourceId() {
@ -64,15 +60,10 @@ public class CommitsActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
@ -85,6 +76,7 @@ public class CommitsActivity extends BaseActivity {
ImageView closeActivity = findViewById(R.id.close);
noData = findViewById(R.id.noDataCommits);
progressLoadMore = findViewById(R.id.progressLoadMore);
progressBar = findViewById(R.id.progress_bar);
SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh);
@ -92,19 +84,19 @@ public class CommitsActivity extends BaseActivity {
closeActivity.setOnClickListener(onClickListener);
// 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;
}
recyclerView = findViewById(R.id.recyclerView);
commitsList = new ArrayList<>();
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
loadInitial(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName);
loadInitial(Authorization.get(ctx), repoOwner, repoName, branchName, resultLimit);
adapter.notifyDataChanged();
}, 200));
adapter = new CommitsAdapter(ctx, commitsList);
@ -113,31 +105,27 @@ public class CommitsActivity extends BaseActivity {
if(commitsList.size() == resultLimit || pageSize == resultLimit) {
int page = (commitsList.size() + resultLimit) / resultLimit;
loadMore(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, page, branchName);
loadMore(Authorization.get(ctx), repoOwner, repoName, page, branchName, resultLimit);
}
}));
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
recyclerView.setAdapter(adapter);
api = AppApiService.createService(ApiInterface.class, instanceUrl, ctx);
loadInitial(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName);
loadInitial(Authorization.get(ctx), repoOwner, repoName, branchName, resultLimit);
}
private void loadInitial(String token, String repoOwner, String repoName, String branchName) {
private void loadInitial(String token, String repoOwner, String repoName, String branchName, int resultLimit) {
Call<List<Commits>> call = api.getRepositoryCommits(token, repoOwner, repoName, 1, branchName);
Call<List<Commits>> call = RetrofitClient.getApiInterface(ctx).getRepositoryCommits(token, repoOwner, repoName, 1, branchName, resultLimit);
call.enqueue(new Callback<List<Commits>>() {
@Override
public void onResponse(@NonNull Call<List<Commits>> call, @NonNull Response<List<Commits>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
assert response.body() != null;
if(response.body().size() > 0) {
@ -146,42 +134,41 @@ public class CommitsActivity extends BaseActivity {
commitsList.addAll(response.body());
adapter.notifyDataChanged();
noData.setVisibility(View.GONE);
}
else {
commitsList.clear();
adapter.notifyDataChanged();
noData.setVisibility(View.VISIBLE);
}
}
if(response.code() == 409) {
progressBar.setVisibility(View.GONE);
noData.setVisibility(View.VISIBLE);
}
else {
Log.e(TAG, String.valueOf(response.code()));
}
progressBar.setVisibility(View.GONE);
}
@Override
public void onFailure(@NonNull Call<List<Commits>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
Toasty.error(ctx, getResources().getString(R.string.errorOnLogin));
}
});
}
private void loadMore(String token, String repoOwner, String repoName, final int page, String branchName) {
private void loadMore(String token, String repoOwner, String repoName, final int page, String branchName, int resultLimit) {
//add loading progress view
commitsList.add(new Commits("load"));
adapter.notifyItemInserted((commitsList.size() - 1));
progressLoadMore.setVisibility(View.VISIBLE);
Call<List<Commits>> call = api.getRepositoryCommits(token, repoOwner, repoName, page, branchName);
Call<List<Commits>> call = RetrofitClient.getApiInterface(ctx).getRepositoryCommits(token, repoOwner, repoName, page, branchName, resultLimit);
call.enqueue(new Callback<List<Commits>>() {
@ -190,41 +177,33 @@ public class CommitsActivity extends BaseActivity {
if(response.isSuccessful()) {
//remove loading view
commitsList.remove(commitsList.size() - 1);
List<Commits> result = response.body();
assert result != null;
if(result.size() > 0) {
pageSize = result.size();
commitsList.addAll(result);
}
else {
Toasty.info(ctx, getString(R.string.noMoreData));
adapter.setMoreDataAvailable(false);
}
adapter.notifyDataChanged();
}
else {
Log.e(TAG, String.valueOf(response.code()));
}
progressLoadMore.setVisibility(View.GONE);
}
@Override
public void onFailure(@NonNull Call<List<Commits>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
Toasty.error(ctx, getResources().getString(R.string.errorOnLogin));
}
});
@ -259,7 +238,6 @@ public class CommitsActivity extends BaseActivity {
});
return super.onCreateOptionsMenu(menu);
}
private void filter(String text) {
@ -267,7 +245,9 @@ public class CommitsActivity extends BaseActivity {
List<Commits> arr = new ArrayList<>();
for(Commits d : commitsList) {
if(d.getCommit().getMessage().toLowerCase().contains(text) || d.getSha().toLowerCase().contains(text)) {
arr.add(d);
}
}
@ -278,6 +258,7 @@ public class CommitsActivity extends BaseActivity {
private void initCloseListener() {
onClickListener = view -> {
getIntent().removeExtra("branchName");
finish();
};

View File

@ -1,30 +1,30 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
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.AppUtil;
import org.mian.gitnex.helpers.Authorization;
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 org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
@ -44,43 +44,48 @@ public class CreateFileActivity extends BaseActivity {
private EditText newFileContent;
private EditText newFileBranchName;
private EditText newFileCommitMessage;
private Spinner newFileBranchesSpinner;
final Context ctx = this;
private Context appCtx;
private AutoCompleteTextView newFileBranchesSpinner;
private String filePath;
private String fileSha;
private int fileAction = 0; // 0 = create, 1 = delete, 2 = edit
List<Branches> branchesList = new ArrayList<>();
private String loginUid;
private String repoOwner;
private String repoName;
private String instanceToken;
private String selectedBranch;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_file;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
loginUid = tinyDB.getString("loginUid");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
repoOwner = parts[0];
repoName = parts[1];
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
closeActivity = findViewById(R.id.close);
newFileName = findViewById(R.id.newFileName);
newFileContent = findViewById(R.id.newFileContent);
newFileBranchName = findViewById(R.id.newFileBranchName);
newFileCommitMessage = findViewById(R.id.newFileCommitMessage);
TextView branchNameId = findViewById(R.id.branchNameId);
TextView branchNameHintText = findViewById(R.id.branchNameHintText);
TextView toolbarTitle = findViewById(R.id.toolbarTitle);
newFileName.requestFocus();
assert imm != null;
@ -91,105 +96,111 @@ public class CreateFileActivity extends BaseActivity {
newFileCreate = findViewById(R.id.newFileCreate);
newFileContent.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", 1) == 1) {
fileAction = getIntent().getIntExtra("fileAction", 1);
filePath = getIntent().getStringExtra("filePath");
String fileContents = getIntent().getStringExtra("fileContents");
fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.deleteFileText, filePath));
newFileCreate.setText(R.string.deleteFile);
newFileName.setText(filePath);
newFileName.setEnabled(false);
newFileName.setFocusable(false);
newFileContent.setText(fileContents);
newFileContent.setEnabled(false);
newFileContent.setFocusable(false);
}
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", 2) == 2) {
fileAction = getIntent().getIntExtra("fileAction", 2);
filePath = getIntent().getStringExtra("filePath");
String fileContents = getIntent().getStringExtra("fileContents");
fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.editFileText, filePath));
newFileCreate.setText(R.string.editFile);
newFileName.setText(filePath);
newFileName.setEnabled(false);
newFileName.setFocusable(false);
newFileContent.setText(fileContents);
}
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
newFileBranchesSpinner = findViewById(R.id.newFileBranchesSpinner);
newFileBranchesSpinner.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
getBranches(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
newFileBranchesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
public void onItemSelected(AdapterView<?> arg0,
View arg1, int arg2, long arg3)
{
Branches bModelValue = (Branches) newFileBranchesSpinner.getSelectedItem();
if(bModelValue.toString().equals("No branch")) {
newFileBranchName.setEnabled(true);
newFileBranchName.setVisibility(View.VISIBLE);
branchNameId.setVisibility(View.VISIBLE);
branchNameHintText.setVisibility(View.VISIBLE);
}
else {
newFileBranchName.setEnabled(false);
newFileBranchName.setVisibility(View.GONE);
branchNameId.setVisibility(View.GONE);
branchNameHintText.setVisibility(View.GONE);
newFileBranchName.setText("");
}
}
public void onNothingSelected(AdapterView<?> arg0) {}
});
getBranches(instanceToken, repoOwner, repoName, loginUid);
disableProcessButton();
if(!connToInternet) {
newFileCreate.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
newFileCreate.setBackground(shape);
} else {
}
else {
newFileCreate.setOnClickListener(createFileListener);
}
}
private View.OnClickListener createFileListener = v -> processNewFile();
private final View.OnClickListener createFileListener = v -> processNewFile();
private void processNewFile() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
String newFileName_ = newFileName.getText().toString();
String newFileContent_ = newFileContent.getText().toString();
String newFileBranchName_ = newFileBranchName.getText().toString();
String newFileCommitMessage_ = newFileCommitMessage.getText().toString();
Branches currentBranch = (Branches) newFileBranchesSpinner.getSelectedItem();
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newFileName_.equals("") || newFileContent_.equals("") || newFileCommitMessage_.equals("")) {
Toasty.info(ctx, getString(R.string.newFileRequiredFields));
Toasty.error(ctx, getString(R.string.newFileRequiredFields));
return;
}
if(currentBranch.toString().equals("No branch")) {
if(selectedBranch.equals("No branch")) {
if(newFileBranchName_.equals("")) {
Toasty.info(ctx, getString(R.string.newFileRequiredFieldNewBranchName));
Toasty.error(ctx, getString(R.string.newFileRequiredFieldNewBranchName));
return;
}
else {
if(!appUtil.checkStringsWithDash(newFileBranchName_)) {
Toasty.info(ctx, getString(R.string.newFileInvalidBranchName));
Toasty.error(ctx, getString(R.string.newFileInvalidBranchName));
return;
}
}
@ -197,31 +208,46 @@ public class CreateFileActivity extends BaseActivity {
if(appUtil.charactersLength(newFileCommitMessage_) > 255) {
Toasty.info(ctx, getString(R.string.newFileCommitMessageError));
Toasty.warning(ctx, getString(R.string.newFileCommitMessageError));
}
else {
disableProcessButton();
createNewFile(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, newFileName_, appUtil.encodeBase64(newFileContent_), newFileBranchName_, newFileCommitMessage_, currentBranch.toString());
if(fileAction == 1) {
deleteFile(Authorization.get(ctx), repoOwner, repoName, filePath,
newFileBranchName_, newFileCommitMessage_, selectedBranch, fileSha);
}
else if(fileAction == 2) {
editFile(Authorization.get(ctx), repoOwner, repoName, filePath,
appUtil.encodeBase64(newFileContent_), newFileBranchName_, newFileCommitMessage_, selectedBranch, fileSha);
}
else {
createNewFile(Authorization.get(ctx), repoOwner, repoName, newFileName_,
appUtil.encodeBase64(newFileContent_), newFileBranchName_, newFileCommitMessage_, selectedBranch);
}
}
}
private void createNewFile(final String instanceUrl, final String token, String repoOwner, String repoName, String fileName, String fileContent, String fileBranchName, String fileCommitMessage, String currentBranch) {
private void createNewFile(final String token, String repoOwner, String repoName, String fileName, String fileContent, String fileBranchName, String fileCommitMessage, String currentBranch) {
NewFile createNewFileJsonStr;
if(currentBranch.equals("No branch")) {
createNewFileJsonStr = new NewFile("", fileContent, fileCommitMessage, fileBranchName);
}
else {
createNewFileJsonStr = new NewFile(currentBranch, fileContent, fileCommitMessage, "");
}
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.createNewFile(token, repoOwner, repoName, fileName, createNewFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@ -232,9 +258,8 @@ public class CreateFileActivity extends BaseActivity {
if(response.code() == 201) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.newFileSuccessMessage));
Toasty.success(ctx, getString(R.string.newFileSuccessMessage));
finish();
}
else if(response.code() == 401) {
@ -243,25 +268,25 @@ public class CreateFileActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound));
Toasty.warning(ctx, getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.orgCreatedError));
Toasty.error(ctx, getString(R.string.orgCreatedError));
}
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -269,12 +294,146 @@ public class CreateFileActivity extends BaseActivity {
}
private void getBranches(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
private void deleteFile(final String token, String repoOwner, String repoName, String fileName, String fileBranchName, String fileCommitMessage, String currentBranch, String fileSha) {
String branchName;
DeleteFile deleteFileJsonStr;
if(currentBranch.equals("No branch")) {
branchName = fileBranchName;
deleteFileJsonStr = new DeleteFile("", fileCommitMessage, fileBranchName, fileSha);
}
else {
branchName = currentBranch;
deleteFileJsonStr = new DeleteFile(currentBranch, fileCommitMessage, "", fileSha);
}
Call<JsonElement> call = RetrofitClient
.getApiInterface(ctx)
.deleteFile(token, repoOwner, repoName, fileName, deleteFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 200) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.deleteFileMessage, branchName));
getIntent().removeExtra("filePath");
getIntent().removeExtra("fileSha");
getIntent().removeExtra("fileContents");
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
}
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void editFile(final String token, String repoOwner, String repoName, String fileName, String fileContent, String fileBranchName, String fileCommitMessage, String currentBranch, String fileSha) {
String branchName;
EditFile editFileJsonStr;
if(currentBranch.equals("No branch")) {
branchName = fileBranchName;
editFileJsonStr = new EditFile("", fileCommitMessage, fileBranchName, fileSha, fileContent);
}
else {
branchName = currentBranch;
editFileJsonStr = new EditFile(currentBranch, fileCommitMessage, "", fileSha, fileContent);
}
Call<JsonElement> call = RetrofitClient
.getApiInterface(ctx)
.editFile(token, repoOwner, repoName, fileName, editFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 200) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.editFileMessage, branchName));
getIntent().removeExtra("filePath");
getIntent().removeExtra("fileSha");
getIntent().removeExtra("fileContents");
tinyDB.putBoolean("fileModified", true);
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
}
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void getBranches(String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getBranches(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
.getApiInterface(ctx)
.getBranches(Authorization.get(ctx), repoOwner, repoName);
call.enqueue(new Callback<List<Branches>>() {
@ -282,37 +441,53 @@ public class CreateFileActivity extends BaseActivity {
public void onResponse(@NonNull Call<List<Branches>> call, @NonNull retrofit2.Response<List<Branches>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Branches> branchesList_ = response.body();
branchesList.add(new Branches("No branch"));
assert branchesList_ != null;
if(branchesList_.size() > 0) {
for (int i = 0; i < branchesList_.size(); i++) {
Branches data = new Branches(
branchesList_.get(i).getName()
);
Branches data = new Branches(branchesList_.get(i).getName());
branchesList.add(data);
}
}
ArrayAdapter<Branches> adapter = new ArrayAdapter<>(CreateFileActivity.this,
R.layout.spinner_item, branchesList);
R.layout.list_spinner_items, branchesList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
newFileBranchesSpinner.setAdapter(adapter);
enableProcessButton();
newFileBranchesSpinner.setOnItemClickListener ((parent, view, position, id) -> {
selectedBranch = branchesList.get(position).getName();
if(selectedBranch.equals("No branch")) {
newFileBranchName.setEnabled(true);
newFileBranchName.setVisibility(View.VISIBLE);
}
else {
newFileBranchName.setEnabled(false);
newFileBranchName.setVisibility(View.GONE);
newFileBranchName.setText("");
}
});
}
}
}
@Override
public void onFailure(@NonNull Call<List<Branches>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
@ -320,27 +495,18 @@ public class CreateFileActivity extends BaseActivity {
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void disableProcessButton() {
newFileCreate.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
newFileCreate.setBackground(shape);
}
private void enableProcessButton() {
newFileCreate.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
newFileCreate.setBackground(shape);
}
}

View File

@ -1,310 +1,268 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.AssigneesActions;
import org.mian.gitnex.actions.LabelsActions;
import org.mian.gitnex.adapters.AssigneesListAdapter;
import org.mian.gitnex.adapters.LabelsListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateIssueBinding;
import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.CreateIssue;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.models.MultiSelectModel;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class CreateIssueActivity extends BaseActivity implements View.OnClickListener {
public class CreateIssueActivity extends BaseActivity implements View.OnClickListener, LabelsListAdapter.LabelsListAdapterListener, AssigneesListAdapter.AssigneesListAdapterListener {
private ActivityCreateIssueBinding viewBinding;
private CustomLabelsSelectionDialogBinding labelsBinding;
private CustomAssigneesSelectionDialogBinding assigneesBinding;
private View.OnClickListener onClickListener;
MultiSelectDialog multiSelectDialog;
MultiSelectDialog multiSelectDialogLabels;
private TextView assigneesList;
private TextView newIssueLabels;
private TextView newIssueDueDate;
private Spinner newIssueMilestoneSpinner;
private EditText newIssueTitle;
private SocialAutoCompleteTextView newIssueDescription;
private Button createNewIssueButton;
private TextView labelsIdHolder;
private boolean assigneesFlag;
private boolean labelsFlag;
final Context ctx = this;
private Context appCtx;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private Dialog dialogLabels;
private Dialog dialogAssignees;
private String labelsSetter;
private String assigneesSetter;
private int milestoneId;
List<Milestones> milestonesList = new ArrayList<>();
ArrayList<MultiSelectModel> listOfAssignees = new ArrayList<>();
ArrayList<MultiSelectModel> listOfLabels= new ArrayList<>();
private ArrayAdapter<Mention> defaultMentionAdapter;
private String loginUid;
private String repoOwner;
private String repoName;
private LabelsListAdapter labelsAdapter;
private AssigneesListAdapter assigneesAdapter;
private List<Integer> labelsIds = new ArrayList<>();
private List<Labels> labelsList = new ArrayList<>();
private List<Milestones> milestonesList = new ArrayList<>();
private List<Collaborators> assigneesList = new ArrayList<>();
private List<String> assigneesListData = new ArrayList<>();
@Override
protected int getLayoutResourceId(){
protected int getLayoutResourceId() {
return R.layout.activity_create_issue;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
viewBinding = ActivityCreateIssueBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String loginFullName = tinyDb.getString("userFullname");
String repoFullName = tinyDb.getString("repoFullName");
loginUid = tinyDB.getString("loginUid");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
repoOwner = parts[0];
repoName = parts[1];
// require gitea 1.12 or higher
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
}
ImageView closeActivity = findViewById(R.id.close);
assigneesList = findViewById(R.id.newIssueAssigneesList);
newIssueLabels = findViewById(R.id.newIssueLabels);
newIssueDueDate = findViewById(R.id.newIssueDueDate);
createNewIssueButton = findViewById(R.id.createNewIssueButton);
newIssueTitle = findViewById(R.id.newIssueTitle);
newIssueDescription = findViewById(R.id.newIssueDescription);
labelsIdHolder = findViewById(R.id.labelsIdHolder);
newIssueTitle.requestFocus();
viewBinding.newIssueTitle.requestFocus();
assert imm != null;
imm.showSoftInput(newIssueTitle, InputMethodManager.SHOW_IMPLICIT);
imm.showSoftInput(viewBinding.newIssueTitle, InputMethodManager.SHOW_IMPLICIT);
defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList();
viewBinding.newIssueDescription.setOnTouchListener((touchView, motionEvent) -> {
newIssueDescription.setMentionAdapter(defaultMentionAdapter);
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
labelsAdapter = new LabelsListAdapter(labelsList, CreateIssueActivity.this, labelsIds);
assigneesAdapter = new AssigneesListAdapter(ctx, assigneesList, CreateIssueActivity.this, assigneesListData);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
viewBinding.close.setOnClickListener(onClickListener);
assigneesList.setOnClickListener(this);
newIssueLabels.setOnClickListener(this);
newIssueDueDate.setOnClickListener(this);
viewBinding.newIssueAssigneesList.setOnClickListener(this);
viewBinding.newIssueLabels.setOnClickListener(this);
viewBinding.newIssueDueDate.setOnClickListener(this);
newIssueMilestoneSpinner = findViewById(R.id.newIssueMilestoneSpinner);
newIssueMilestoneSpinner.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
getMilestones(instanceUrl, instanceToken, repoOwner, repoName, loginUid, resultLimit);
getLabels(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
getCollaborators(instanceUrl, instanceToken, repoOwner, repoName, loginUid, loginFullName);
getMilestones(repoOwner, repoName, resultLimit);
disableProcessButton();
viewBinding.newIssueLabels.setOnClickListener(newIssueLabels -> showLabels());
viewBinding.newIssueAssigneesList.setOnClickListener(newIssueAssigneesList -> showAssignees());
if(!connToInternet) {
createNewIssueButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewIssueButton.setBackground(shape);
} else {
createNewIssueButton.setOnClickListener(this);
viewBinding.createNewIssueButton.setEnabled(false);
}
else {
viewBinding.createNewIssueButton.setOnClickListener(this);
}
}
@Override
public void assigneesInterface(List<String> data) {
assigneesSetter = String.valueOf(data);
viewBinding.newIssueAssigneesList.setText(assigneesSetter.replace("]", "").replace("[", ""));
assigneesListData = data;
}
@Override
public void labelsInterface(List<String> data) {
labelsSetter = String.valueOf(data);
viewBinding.newIssueLabels.setText(labelsSetter.replace("]", "").replace("[", ""));
}
@Override
public void labelsIdsInterface(List<Integer> data) {
labelsIds = data;
}
private void showAssignees() {
dialogAssignees = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogAssignees.getWindow() != null) {
dialogAssignees.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
assigneesBinding = CustomAssigneesSelectionDialogBinding.inflate(LayoutInflater.from(ctx));
View view = assigneesBinding.getRoot();
dialogAssignees.setContentView(view);
assigneesBinding.cancel.setOnClickListener(assigneesBinding_ -> dialogAssignees.dismiss());
dialogAssignees.show();
AssigneesActions.getRepositoryAssignees(ctx, repoOwner, repoName, assigneesList, dialogAssignees, assigneesAdapter, assigneesBinding);
}
private void showLabels() {
dialogLabels = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogLabels.getWindow() != null) {
dialogLabels.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
labelsBinding = CustomLabelsSelectionDialogBinding.inflate(LayoutInflater.from(ctx));
View view = labelsBinding.getRoot();
dialogLabels.setContentView(view);
labelsBinding.cancel.setOnClickListener(labelsBinding_ -> dialogLabels.dismiss());
dialogLabels.show();
LabelsActions.getRepositoryLabels(ctx, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
}
private void processNewIssue() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
Milestones mModel = (Milestones) newIssueMilestoneSpinner.getSelectedItem();
int newIssueMilestoneIdForm = mModel.getId();
String newIssueTitleForm = newIssueTitle.getText().toString();
String newIssueDescriptionForm = newIssueDescription.getText().toString();
String newIssueAssigneesListForm = assigneesList.getText().toString();
//String newIssueLabelsForm = newIssueLabels.getText().toString();
String newIssueDueDateForm = newIssueDueDate.getText().toString();
String newIssueLabelsIdHolderForm = labelsIdHolder.getText().toString();
String newIssueTitleForm = Objects.requireNonNull(viewBinding.newIssueTitle.getText()).toString();
String newIssueDescriptionForm = Objects.requireNonNull(viewBinding.newIssueDescription.getText()).toString();
String newIssueDueDateForm = Objects.requireNonNull(viewBinding.newIssueDueDate.getText()).toString();
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (newIssueTitleForm.equals("")) {
Toasty.info(ctx, getString(R.string.issueTitleEmpty));
Toasty.error(ctx, getString(R.string.issueTitleEmpty));
return;
}
/*if (newIssueDescriptionForm.equals("")) {
Toasty.info(ctx, getString(R.string.issueDescriptionEmpty));
return;
}*/
if (newIssueDueDateForm.equals("")) {
newIssueDueDateForm = null;
} else {
}
else {
newIssueDueDateForm = (AppUtil.customDateCombine(AppUtil.customDateFormat(newIssueDueDateForm)));
}
List<String> newIssueAssigneesListForm_ = new ArrayList<>(Arrays.asList(newIssueAssigneesListForm.split(",")));
for (int i = 0; i < newIssueAssigneesListForm_.size(); i++) {
newIssueAssigneesListForm_.set(i, newIssueAssigneesListForm_.get(i).trim());
}
int[] integers;
if (!newIssueLabelsIdHolderForm.equals("")) {
String[] items = newIssueLabelsIdHolderForm.replaceAll("\\[", "").replaceAll("\\]", "").replaceAll("\\s", "").split(",");
integers = new int[items.length];
for (int i = 0; i < integers.length; i++) {
integers[i] = Integer.parseInt(items[i]);
}
}
else {
integers = new int[0];
}
//Log.i("FormData", String.valueOf(newIssueLabelsForm));
disableProcessButton();
createNewIssueFunc(instanceUrl, instanceToken, repoOwner, repoName, loginUid, newIssueDescriptionForm, newIssueDueDateForm, newIssueMilestoneIdForm, newIssueTitleForm, newIssueAssigneesListForm_, integers);
createNewIssueFunc(repoOwner, repoName, loginUid, newIssueDescriptionForm, newIssueDueDateForm, milestoneId, newIssueTitleForm);
}
public void loadCollaboratorsList() {
private void createNewIssueFunc(String repoOwner, String repoName, String loginUid, String newIssueDescriptionForm, String newIssueDueDateForm, int newIssueMilestoneIdForm, String newIssueTitleForm) {
final TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
String fullName = "";
for (int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(
new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
} else {
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.toString());
}
});
}
private void createNewIssueFunc(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String loginUid, String newIssueDescriptionForm, String newIssueDueDateForm, int newIssueMilestoneIdForm, String newIssueTitleForm, List<String> newIssueAssigneesListForm, int[] newIssueLabelsForm) {
CreateIssue createNewIssueJson = new CreateIssue(loginUid, newIssueDescriptionForm, false, newIssueDueDateForm, newIssueMilestoneIdForm, newIssueTitleForm, newIssueAssigneesListForm, newIssueLabelsForm);
CreateIssue createNewIssueJson = new CreateIssue(loginUid, newIssueDescriptionForm, false, newIssueDueDateForm, newIssueMilestoneIdForm, newIssueTitleForm, assigneesListData, labelsIds);
Call<JsonElement> call3;
call3 = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.createNewIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, createNewIssueJson);
.getApiInterface(ctx)
.createNewIssue(Authorization.get(ctx), repoOwner, repoName, createNewIssueJson);
call3.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response2) {
if(response2.isSuccessful()) {
if(response2.code() == 201) {
if(response2.code() == 201) {
//Log.i("isSuccessful1", String.valueOf(response2.body()));
TinyDB tinyDb = new TinyDB(appCtx);
tinyDb.putBoolean("resumeIssues", true);
Toasty.info(ctx, getString(R.string.issueCreated));
enableProcessButton();
finish();
}
TinyDB tinyDb = TinyDB.getInstance(appCtx);
tinyDb.putBoolean("resumeIssues", true);
Toasty.success(ctx, getString(R.string.issueCreated));
enableProcessButton();
finish();
}
else if(response2.code() == 401) {
@ -313,21 +271,19 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.info(ctx, getString(R.string.issueCreatedError));
Toasty.error(ctx, getString(R.string.issueCreatedError));
enableProcessButton();
//Log.i("isSuccessful2", String.valueOf(response2.body()));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
Toasty.error(ctx, getString(R.string.genericServerResponseError));
enableProcessButton();
}
});
@ -335,21 +291,16 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
private void getMilestones(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid, int resultLimit) {
private void getMilestones(String repoOwner, String repoName, int resultLimit) {
String msState = "open";
Call<List<Milestones>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getMilestones(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, 1, resultLimit, msState);
.getApiInterface(ctx)
.getMilestones(Authorization.get(ctx), repoOwner, repoName, 1, resultLimit, msState);
call.enqueue(new Callback<List<Milestones>>() {
@ -357,13 +308,16 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
public void onResponse(@NonNull Call<List<Milestones>> call, @NonNull retrofit2.Response<List<Milestones>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Milestones> milestonesList_ = response.body();
milestonesList.add(new Milestones(0,getString(R.string.issueCreatedNoMilestone)));
assert milestonesList_ != null;
if(milestonesList_.size() > 0) {
for (int i = 0; i < milestonesList_.size(); i++) {
//Don't translate "open" is a enum
@ -374,17 +328,20 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
);
milestonesList.add(data);
}
}
}
ArrayAdapter<Milestones> adapter = new ArrayAdapter<>(CreateIssueActivity.this,
R.layout.spinner_item, milestonesList);
R.layout.list_spinner_items, milestonesList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
newIssueMilestoneSpinner.setAdapter(adapter);
viewBinding.newIssueMilestoneSpinner.setAdapter(adapter);
enableProcessButton();
viewBinding.newIssueMilestoneSpinner.setOnItemClickListener ((parent, view, position, id) ->
milestoneId = milestonesList.get(position).getId()
);
}
}
@ -392,143 +349,8 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
@Override
public void onFailure(@NonNull Call<List<Milestones>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void getCollaborators(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid, String loginFullName) {
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
listOfAssignees.add(new MultiSelectModel(-1, loginFullName));
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull retrofit2.Response<List<Collaborators>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Collaborators> assigneesList_ = response.body();
assert assigneesList_ != null;
if(assigneesList_.size() > 0) {
for (int i = 0; i < assigneesList_.size(); i++) {
/*String assigneesCopy;
if(!assigneesList_.get(i).getFull_name().equals("")) {
assigneesCopy = getString(R.string.dialogAssignessText, assigneesList_.get(i).getFull_name(), assigneesList_.get(i).getLogin());
}
else {
assigneesCopy = assigneesList_.get(i).getLogin();
}*/
listOfAssignees.add(new MultiSelectModel(assigneesList_.get(i).getId(), assigneesList_.get(i).getLogin().trim()));
}
assigneesFlag = true;
}
multiSelectDialog = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectAssigneesListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.okButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.setMaxSelectionLimit(listOfAssignees.size())
.multiSelectList(listOfAssignees)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
assigneesList.setText(dataString);
}
@Override
public void onCancel() {
//Log.d("multiSelect","Dialog cancelled");
}
});
}
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void getLabels(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getlabels(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Labels> labelsList_ = response.body();
assert labelsList_ != null;
if(labelsList_.size() > 0) {
for (int i = 0; i < labelsList_.size(); i++) {
listOfLabels.add(new MultiSelectModel(labelsList_.get(i).getId(), labelsList_.get(i).getName().trim()));
}
labelsFlag = true;
}
multiSelectDialogLabels = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectLabelsListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.okButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.setMaxSelectionLimit(listOfLabels.size())
.multiSelectList(listOfLabels)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
newIssueLabels.setText(dataString.trim());
labelsIdHolder.setText(selectedIds.toString());
}
@Override
public void onCancel() {
//Log.d("multiSelect","Dialog cancelled");
}
});
}
}
}
@Override
public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
@ -536,23 +358,8 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
@Override
public void onClick(View v) {
if (v == assigneesList) {
if(assigneesFlag) {
multiSelectDialog.show(getSupportFragmentManager(), "multiSelectDialog");
}
else {
Toasty.info(ctx, getResources().getString(R.string.noAssigneesFound));
}
}
else if (v == newIssueLabels) {
if(labelsFlag) {
multiSelectDialogLabels.show(getSupportFragmentManager(), "multiSelectDialogLabels");
}
else {
Toasty.info(ctx, getResources().getString(R.string.noLabelsFound));
}
}
else if (v == newIssueDueDate) {
if (v == viewBinding.newIssueDueDate) {
final Calendar c = Calendar.getInstance();
int mYear = c.get(Calendar.YEAR);
@ -560,41 +367,22 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
final int mDay = c.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(this,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
newIssueDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth));
}
}, mYear, mMonth, mDay);
(view, year, monthOfYear, dayOfMonth) -> viewBinding.newIssueDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth)), mYear, mMonth, mDay);
datePickerDialog.show();
}
else if(v == createNewIssueButton) {
else if(v == viewBinding.createNewIssueButton) {
processNewIssue();
}
}
private void disableProcessButton() {
createNewIssueButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewIssueButton.setBackground(shape);
viewBinding.createNewIssueButton.setEnabled(false);
}
private void enableProcessButton() {
createNewIssueButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createNewIssueButton.setBackground(shape);
viewBinding.createNewIssueButton.setEnabled(true);
}
}

View File

@ -1,13 +1,7 @@
package org.mian.gitnex.activities;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
@ -16,19 +10,22 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import com.pes.androidmaterialcolorpickerdialog.ColorPickerCallback;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.CreateLabel;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.LabelsViewModel;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
@ -40,8 +37,6 @@ public class CreateLabelActivity extends BaseActivity {
private TextView colorPicker;
private EditText labelName;
private Button createLabelButton;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
@ -52,28 +47,26 @@ public class CreateLabelActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
final TinyDB tinyDb = new TinyDB(appCtx);
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(getIntent().getStringExtra("labelAction") != null && Objects.requireNonNull(getIntent().getStringExtra("labelAction")).equals("delete")) {
deleteLabel(instanceUrl, instanceToken, repoOwner, repoName, Integer.parseInt(Objects.requireNonNull(getIntent().getStringExtra("labelId"))), loginUid);
deleteLabel(instanceToken, repoOwner, repoName, Integer.parseInt(Objects.requireNonNull(getIntent().getStringExtra("labelId"))), loginUid);
finish();
return;
}
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
ImageView closeActivity = findViewById(R.id.close);
colorPicker = findViewById(R.id.colorPicker);
@ -88,22 +81,14 @@ public class CreateLabelActivity extends BaseActivity {
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
colorPicker.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
cp.show();
}
});
colorPicker.setOnClickListener(v -> cp.show());
cp.setCallback(new ColorPickerCallback() {
@Override
public void onColorChosen(@ColorInt int color) {
cp.setCallback(color -> {
//Log.i("#Hex no alpha", String.format("#%06X", (0xFFFFFF & color)));
colorPicker.setBackgroundColor(color);
tinyDb.putString("labelColor", String.format("#%06X", (0xFFFFFF & color)));
cp.dismiss();
}
//Log.i("#Hex no alpha", String.format("#%06X", (0xFFFFFF & color)));
colorPicker.setBackgroundColor(color);
tinyDb.putString("labelColor", String.format("#%06X", (0xFFFFFF & color)));
cp.dismiss();
});
if(getIntent().getStringExtra("labelAction") != null && Objects.requireNonNull(getIntent().getStringExtra("labelAction")).equals("edit")) {
@ -118,49 +103,33 @@ public class CreateLabelActivity extends BaseActivity {
createLabelButton.setText(getResources().getString(R.string.newUpdateButtonCopy));
createLabelButton.setOnClickListener(updateLabelListener);
return;
}
if(!connToInternet) {
createLabelButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createLabelButton.setBackground(shape);
} else {
}
else {
createLabelButton.setOnClickListener(createLabelListener);
}
}
private View.OnClickListener createLabelListener = new View.OnClickListener() {
public void onClick(View v) {
processCreateLabel();
}
};
private final View.OnClickListener createLabelListener = v -> processCreateLabel();
private View.OnClickListener updateLabelListener = new View.OnClickListener() {
public void onClick(View v) {
processUpdateLabel();
}
};
private final View.OnClickListener updateLabelListener = v -> processUpdateLabel();
private void processUpdateLabel() {
final TinyDB tinyDb = new TinyDB(appCtx);
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
@ -168,97 +137,94 @@ public class CreateLabelActivity extends BaseActivity {
String updateLabelColor;
if(tinyDb.getString("labelColor").isEmpty()) {
updateLabelColor = tinyDb.getString("labelColorDefault");
}
else {
updateLabelColor = tinyDb.getString("labelColor");
}
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(updateLabelName.equals("")) {
Toasty.info(ctx, getString(R.string.labelEmptyError));
Toasty.error(ctx, getString(R.string.labelEmptyError));
return;
}
if(!appUtil.checkStrings(updateLabelName)) {
Toasty.info(ctx, getString(R.string.labelNameError));
Toasty.error(ctx, getString(R.string.labelNameError));
return;
}
disableProcessButton();
patchLabel(instanceUrl, instanceToken, repoOwner, repoName, updateLabelName, updateLabelColor, Integer.valueOf(getIntent().getStringExtra("labelId")), loginUid);
patchLabel(instanceToken, repoOwner, repoName, updateLabelName, updateLabelColor, Integer.parseInt(
Objects.requireNonNull(getIntent().getStringExtra("labelId"))), loginUid);
}
private void processCreateLabel() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String newLabelName = labelName.getText().toString();
String newLabelColor;
if(tinyDb.getString("labelColor").isEmpty()) {
newLabelColor = String.format("#%06X", (0xFFFFFF & ContextCompat.getColor(ctx, R.color.releasePre)));
}
else {
newLabelColor = tinyDb.getString("labelColor");
}
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newLabelName.equals("")) {
Toasty.info(ctx, getString(R.string.labelEmptyError));
Toasty.error(ctx, getString(R.string.labelEmptyError));
return;
}
if(!appUtil.checkStrings(newLabelName)) {
Toasty.info(ctx, getString(R.string.labelNameError));
Toasty.error(ctx, getString(R.string.labelNameError));
return;
}
disableProcessButton();
createNewLabel(instanceUrl, instanceToken, repoOwner, repoName, newLabelName, newLabelColor, loginUid);
createNewLabel(instanceToken, repoOwner, repoName, newLabelName, newLabelColor, loginUid);
}
private void createNewLabel(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String newLabelName, String newLabelColor, String loginUid) {
private void createNewLabel(final String instanceToken, String repoOwner, String repoName, String newLabelName, String newLabelColor, String loginUid) {
CreateLabel createLabelFunc = new CreateLabel(newLabelName, newLabelColor);
final TinyDB tinyDb = new TinyDB(appCtx);
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
Call<CreateLabel> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.createLabel(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, createLabelFunc);
.getApiInterface(ctx)
.createLabel(Authorization.get(ctx), repoOwner, repoName, createLabelFunc);
call.enqueue(new Callback<CreateLabel>() {
@ -267,11 +233,10 @@ public class CreateLabelActivity extends BaseActivity {
if(response.code() == 201) {
Toasty.info(ctx, getString(R.string.labelCreated));
Toasty.success(ctx, getString(R.string.labelCreated));
tinyDb.putString("labelColor", "");
tinyDb.putBoolean("labelsRefresh", true);
finish();
}
else if(response.code() == 401) {
@ -280,20 +245,18 @@ public class CreateLabelActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
tinyDb.putString("labelColor", "");
Toasty.info(ctx, getString(R.string.labelGeneralError));
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<CreateLabel> call, @NonNull Throwable t) {
tinyDb.putString("labelColor", "");
Log.e("onFailure", t.toString());
enableProcessButton();
@ -302,17 +265,16 @@ public class CreateLabelActivity extends BaseActivity {
}
private void patchLabel(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String updateLabelName, String updateLabelColor, int labelId, String loginUid) {
private void patchLabel(final String instanceToken, String repoOwner, String repoName, String updateLabelName, String updateLabelColor, int labelId, String loginUid) {
CreateLabel createLabelFunc = new CreateLabel(updateLabelName, updateLabelColor);
final TinyDB tinyDb = new TinyDB(appCtx);
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
Call<CreateLabel> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.patchLabel(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, labelId, createLabelFunc);
.getApiInterface(appCtx)
.patchLabel(Authorization.get(ctx), repoOwner, repoName, labelId, createLabelFunc);
call.enqueue(new Callback<CreateLabel>() {
@ -320,9 +282,10 @@ public class CreateLabelActivity extends BaseActivity {
public void onResponse(@NonNull Call<CreateLabel> call, @NonNull retrofit2.Response<CreateLabel> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
Toasty.info(ctx, getString(R.string.labelUpdated));
Toasty.success(ctx, getString(R.string.labelUpdated));
tinyDb.putString("labelColor", "");
tinyDb.putBoolean("labelsRefresh", true);
tinyDb.putString("labelColorDefault", "");
@ -331,7 +294,6 @@ public class CreateLabelActivity extends BaseActivity {
getIntent().removeExtra("labelTitle");
getIntent().removeExtra("labelColor");
finish();
}
}
else if(response.code() == 401) {
@ -341,21 +303,19 @@ public class CreateLabelActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
tinyDb.putString("labelColor", "");
tinyDb.putString("labelColorDefault", "");
Toasty.info(ctx, getString(R.string.labelGeneralError));
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<CreateLabel> call, @NonNull Throwable t) {
tinyDb.putString("labelColor", "");
tinyDb.putString("labelColorDefault", "");
Log.e("onFailure", t.toString());
@ -366,26 +326,24 @@ public class CreateLabelActivity extends BaseActivity {
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId");
getIntent().removeExtra("labelTitle");
getIntent().removeExtra("labelColor");
finish();
}
onClickListener = view -> {
getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId");
getIntent().removeExtra("labelTitle");
getIntent().removeExtra("labelColor");
finish();
};
}
private void deleteLabel(final String instanceUrl, final String instanceToken, final String repoOwner, final String repoName, int labelId, String loginUid) {
private void deleteLabel(final String instanceToken, final String repoOwner, final String repoName, int labelId, String loginUid) {
Call<Labels> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.deleteLabel(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, labelId);
.getApiInterface(appCtx)
.deleteLabel(Authorization.get(ctx), repoOwner, repoName, labelId);
call.enqueue(new Callback<Labels>() {
@ -393,13 +351,13 @@ public class CreateLabelActivity extends BaseActivity {
public void onResponse(@NonNull Call<Labels> call, @NonNull retrofit2.Response<Labels> response) {
if(response.isSuccessful()) {
if(response.code() == 204) {
Toasty.info(ctx, getString(R.string.labelDeleteText));
LabelsViewModel.loadLabelsList(instanceUrl, instanceToken, repoOwner, repoName, ctx);
Toasty.success(ctx, getString(R.string.labelDeleteText));
LabelsViewModel.loadLabelsList(instanceToken, repoOwner, repoName, ctx);
getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId");
}
}
else if(response.code() == 401) {
@ -408,14 +366,11 @@ public class CreateLabelActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.info(ctx, getString(R.string.labelDeleteErrorText));
Toasty.error(ctx, getString(R.string.labelDeleteErrorText));
}
}
@Override
@ -429,21 +384,11 @@ public class CreateLabelActivity extends BaseActivity {
private void disableProcessButton() {
createLabelButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createLabelButton.setBackground(shape);
}
private void enableProcessButton() {
createLabelButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createLabelButton.setBackground(shape);
}
}
}

View File

@ -1,29 +1,29 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.Calendar;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
@ -36,21 +36,19 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
private EditText milestoneTitle;
private EditText milestoneDescription;
private Button createNewMilestoneButton;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_milestone;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -64,6 +62,17 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
assert imm != null;
imm.showSoftInput(milestoneTitle, InputMethodManager.SHOW_IMPLICIT);
milestoneDescription.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
milestoneDueDate.setOnClickListener(this);
@ -71,38 +80,25 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
if(!connToInternet) {
createNewMilestoneButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewMilestoneButton.setBackground(shape);
} else {
}
else {
createNewMilestoneButton.setOnClickListener(createMilestoneListener);
}
}
private View.OnClickListener createMilestoneListener = new View.OnClickListener() {
public void onClick(View v) {
processNewMilestone();
}
};
private final View.OnClickListener createMilestoneListener = v -> processNewMilestone();
private void processNewMilestone() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
//String appLocale = tinyDb.getString("locale");
String newMilestoneTitle = milestoneTitle.getText().toString();
String newMilestoneDescription = milestoneDescription.getText().toString();
@ -110,50 +106,50 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newMilestoneTitle.equals("")) {
Toasty.info(ctx, getString(R.string.milestoneNameErrorEmpty));
Toasty.error(ctx, getString(R.string.milestoneNameErrorEmpty));
return;
}
if(!newMilestoneDescription.equals("")) {
if (appUtil.charactersLength(newMilestoneDescription) > 255) {
Toasty.info(ctx, getString(R.string.milestoneDescError));
Toasty.warning(ctx, getString(R.string.milestoneDescError));
return;
}
}
String finalMilestoneDueDate = null;
if(!newMilestoneDueDate.isEmpty()) {
finalMilestoneDueDate = (AppUtil.customDateCombine(AppUtil.customDateFormat(newMilestoneDueDate)));
} else if (new Version(tinyDb.getString("giteaVersion")).less("1.10.0")) {
}
else if (new Version(tinyDb.getString("giteaVersion")).less("1.10.0")) {
// if Gitea version is less than 1.10.0 DueDate is required
Toasty.info(ctx, getString(R.string.milestoneDateEmpty));
Toasty.warning(ctx, getString(R.string.milestoneDateEmpty));
return;
}
disableProcessButton();
createNewMilestone(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, newMilestoneTitle, newMilestoneDescription, finalMilestoneDueDate);
createNewMilestone(Authorization.get(ctx), repoOwner, repoName, newMilestoneTitle, newMilestoneDescription, finalMilestoneDueDate);
}
private void createNewMilestone(final String instanceUrl, final String token, String repoOwner, String repoName, String newMilestoneTitle, String newMilestoneDescription, String newMilestoneDueDate) {
private void createNewMilestone(final String token, String repoOwner, String repoName, String newMilestoneTitle, String newMilestoneDescription, String newMilestoneDueDate) {
Milestones createMilestone = new Milestones(newMilestoneDescription, newMilestoneTitle, newMilestoneDueDate);
Call<Milestones> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(appCtx)
.createMilestone(token, repoOwner, repoName, createMilestone);
call.enqueue(new Callback<Milestones>() {
@ -162,14 +158,14 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
public void onResponse(@NonNull Call<Milestones> call, @NonNull retrofit2.Response<Milestones> response) {
if(response.isSuccessful()) {
if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
tinyDb.putBoolean("milestoneCreated", true);
Toasty.info(ctx, getString(R.string.milestoneCreated));
Toasty.success(ctx, getString(R.string.milestoneCreated));
enableProcessButton();
finish();
}
}
else if(response.code() == 401) {
@ -179,19 +175,17 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.milestoneCreatedError));
Toasty.error(ctx, getString(R.string.milestoneCreatedError));
}
}
@Override
public void onFailure(@NonNull Call<Milestones> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -210,48 +204,25 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
final int mDay = c.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(this,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
milestoneDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth));
}
}, mYear, mMonth, mDay);
(view, year, monthOfYear, dayOfMonth) -> milestoneDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth)), mYear, mMonth, mDay);
datePickerDialog.show();
}
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
private void disableProcessButton() {
createNewMilestoneButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewMilestoneButton.setBackground(shape);
}
private void enableProcessButton() {
createNewMilestoneButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createNewMilestoneButton.setBackground(shape);
}
}

View File

@ -1,10 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.util.Patterns;
@ -13,14 +9,17 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
@ -34,8 +33,6 @@ public class CreateNewUserActivity extends BaseActivity {
private EditText userEmail;
private EditText userPassword;
private Button createUserButton;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
@ -46,9 +43,8 @@ public class CreateNewUserActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -69,23 +65,18 @@ public class CreateNewUserActivity extends BaseActivity {
if(!connToInternet) {
disableProcessButton();
} else {
}
else {
createUserButton.setOnClickListener(createNewUserListener);
}
}
private void processCreateNewUser() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
TinyDB tinyDb = TinyDB.getInstance(appCtx);
String newFullName = fullName.getText().toString().trim();
String newUserName = userUserName.getText().toString().trim();
@ -94,53 +85,46 @@ public class CreateNewUserActivity extends BaseActivity {
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newFullName.equals("") || newUserName.equals("") | newUserEmail.equals("") || newUserPassword.equals("")) {
Toasty.info(ctx, getString(R.string.emptyFields));
Toasty.error(ctx, getString(R.string.emptyFields));
return;
}
if(!appUtil.checkStrings(newFullName)) {
Toasty.info(ctx, getString(R.string.userInvalidFullName));
Toasty.error(ctx, getString(R.string.userInvalidFullName));
return;
}
if(!appUtil.checkStringsWithAlphaNumeric(newUserName)) {
Toasty.info(ctx, getString(R.string.userInvalidUserName));
Toasty.error(ctx, getString(R.string.userInvalidUserName));
return;
}
if(!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) {
Toasty.info(ctx, getString(R.string.userInvalidEmail));
Toasty.error(ctx, getString(R.string.userInvalidEmail));
return;
}
disableProcessButton();
createNewUser(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), newFullName, newUserName, newUserEmail, newUserPassword);
createNewUser(Authorization.get(ctx), newFullName, newUserName, newUserEmail, newUserPassword);
}
private void createNewUser(final String instanceUrl, final String instanceToken, String newFullName, String newUserName, String newUserEmail, String newUserPassword) {
private void createNewUser(final String instanceToken, String newFullName, String newUserName, String newUserEmail, String newUserPassword) {
UserInfo createUser = new UserInfo(newUserEmail, newFullName, newUserName, newUserPassword, newUserName, 0, true);
Call<UserInfo> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(appCtx)
.createNewUser(instanceToken, createUser);
call.enqueue(new Callback<UserInfo>() {
@ -150,10 +134,9 @@ public class CreateNewUserActivity extends BaseActivity {
if(response.code() == 201) {
Toasty.info(ctx, getString(R.string.userCreatedText));
Toasty.success(ctx, getString(R.string.userCreatedText));
enableProcessButton();
finish();
}
else if(response.code() == 401) {
@ -162,37 +145,32 @@ public class CreateNewUserActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else if(response.code() == 422) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.userExistsError));
Toasty.warning(ctx, ctx.getString(R.string.userExistsError));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<UserInfo> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -200,39 +178,21 @@ public class CreateNewUserActivity extends BaseActivity {
}
private View.OnClickListener createNewUserListener = new View.OnClickListener() {
public void onClick(View v) {
processCreateNewUser();
}
};
private final View.OnClickListener createNewUserListener = v -> processCreateNewUser();
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
private void disableProcessButton() {
createUserButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createUserButton.setBackground(shape);
}
private void enableProcessButton() {
createUserButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createUserButton.setBackground(shape);
}
}

View File

@ -1,23 +1,24 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import androidx.annotation.NonNull;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserOrganizations;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import retrofit2.Call;
import retrofit2.Callback;
@ -33,21 +34,19 @@ public class CreateOrganizationActivity extends BaseActivity {
private EditText orgName;
private EditText orgDesc;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_organization;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -59,6 +58,17 @@ public class CreateOrganizationActivity extends BaseActivity {
assert imm != null;
imm.showSoftInput(orgName, InputMethodManager.SHOW_IMPLICIT);
orgDesc.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
@ -67,88 +77,67 @@ public class CreateOrganizationActivity extends BaseActivity {
if(!connToInternet) {
createOrganizationButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createOrganizationButton.setBackground(shape);
} else {
}
else {
createOrganizationButton.setOnClickListener(createOrgListener);
}
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
private View.OnClickListener createOrgListener = new View.OnClickListener() {
public void onClick(View v) {
processNewOrganization();
}
};
private final View.OnClickListener createOrgListener = v -> processNewOrganization();
private void processNewOrganization() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
TinyDB tinyDb = TinyDB.getInstance(appCtx);
String newOrgName = orgName.getText().toString();
String newOrgDesc = orgDesc.getText().toString();
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(!newOrgDesc.equals("")) {
if (appUtil.charactersLength(newOrgDesc) > 255) {
Toasty.info(ctx, getString(R.string.orgDescError));
Toasty.warning(ctx, getString(R.string.orgDescError));
return;
}
}
if(newOrgName.equals("")) {
Toasty.info(ctx, getString(R.string.orgNameErrorEmpty));
Toasty.error(ctx, getString(R.string.orgNameErrorEmpty));
}
else if(!appUtil.checkStrings(newOrgName)) {
Toasty.info(ctx, getString(R.string.orgNameErrorInvalid));
Toasty.warning(ctx, getString(R.string.orgNameErrorInvalid));
}
else {
disableProcessButton();
createNewOrganization(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), newOrgName, newOrgDesc);
createNewOrganization(Authorization.get(ctx), newOrgName, newOrgDesc);
}
}
private void createNewOrganization(final String instanceUrl, final String token, String orgName, String orgDesc) {
private void createNewOrganization(final String token, String orgName, String orgDesc) {
UserOrganizations createOrganization = new UserOrganizations(orgName, null, orgDesc, null, null);
Call<UserOrganizations> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(appCtx)
.createNewOrganization(token, createOrganization);
call.enqueue(new Callback<UserOrganizations>() {
@ -158,12 +147,11 @@ public class CreateOrganizationActivity extends BaseActivity {
if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
tinyDb.putBoolean("orgCreated", true);
enableProcessButton();
Toasty.info(ctx, getString(R.string.orgCreated));
Toasty.success(ctx, getString(R.string.orgCreated));
finish();
}
else if(response.code() == 401) {
@ -172,37 +160,35 @@ public class CreateOrganizationActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 409) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.orgExistsError));
Toasty.warning(ctx, getString(R.string.orgExistsError));
}
else if(response.code() == 422) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.orgExistsError));
Toasty.warning(ctx, getString(R.string.orgExistsError));
}
else {
if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound));
Toasty.warning(ctx, getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.orgCreatedError));
Toasty.error(ctx, getString(R.string.orgCreatedError));
}
}
}
@Override
public void onFailure(@NonNull Call<UserOrganizations> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -213,21 +199,11 @@ public class CreateOrganizationActivity extends BaseActivity {
private void disableProcessButton() {
createOrganizationButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createOrganizationButton.setBackground(shape);
}
private void enableProcessButton() {
createOrganizationButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createOrganizationButton.setBackground(shape);
}
}

View File

@ -0,0 +1,383 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.LabelsActions;
import org.mian.gitnex.adapters.LabelsListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreatePrBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.CreatePullRequest;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.Milestones;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class CreatePullRequestActivity extends BaseActivity implements LabelsListAdapter.LabelsListAdapterListener {
private View.OnClickListener onClickListener;
private ActivityCreatePrBinding viewBinding;
private CustomLabelsSelectionDialogBinding labelsBinding;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private Dialog dialogLabels;
private String labelsSetter;
private List<Integer> labelsIds = new ArrayList<>();
private List<String> assignees = new ArrayList<>();
private int milestoneId;
private String loginUid;
private String instanceToken;
private String repoOwner;
private String repoName;
private LabelsListAdapter labelsAdapter;
List<Milestones> milestonesList = new ArrayList<>();
List<Branches> branchesList = new ArrayList<>();
List<Labels> labelsList = new ArrayList<>();
public CreatePullRequestActivity() {
}
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_pr;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewBinding = ActivityCreatePrBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
loginUid = tinyDB.getString("loginUid");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repoOwner = parts[0];
repoName = parts[1];
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
// require gitea 1.12 or higher
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
}
viewBinding.prBody.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
labelsAdapter = new LabelsListAdapter(labelsList, CreatePullRequestActivity.this, labelsIds);
ImageView closeActivity = findViewById(R.id.close);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
viewBinding.prDueDate.setOnClickListener(dueDate ->
setDueDate()
);
disableProcessButton();
getMilestones(repoOwner, repoName, resultLimit);
getBranches(repoOwner, repoName);
viewBinding.prLabels.setOnClickListener(prLabels -> showLabels());
viewBinding.createPr.setOnClickListener(createPr -> processPullRequest());
}
private void processPullRequest() {
String prTitle = String.valueOf(viewBinding.prTitle.getText());
String prDescription = String.valueOf(viewBinding.prBody.getText());
String mergeInto = viewBinding.mergeIntoBranchSpinner.getText().toString();
String pullFrom = viewBinding.pullFromBranchSpinner.getText().toString();
String dueDate = String.valueOf(viewBinding.prDueDate.getText());
assignees.add("");
if (labelsIds.size() == 0) {
labelsIds.add(0);
}
if (dueDate.matches("")) {
dueDate = null;
}
else {
dueDate = AppUtil.customDateCombine(AppUtil.customDateFormat(dueDate));
}
if(prTitle.matches("")) {
Toasty.error(ctx, getString(R.string.titleError));
}
else if(mergeInto.matches("")) {
Toasty.error(ctx, getString(R.string.mergeIntoError));
}
else if(pullFrom.matches("")) {
Toasty.error(ctx, getString(R.string.pullFromError));
}
else if(pullFrom.equals(mergeInto)) {
Toasty.error(ctx, getString(R.string.sameBranchesError));
}
else {
createPullRequest(prTitle, prDescription, mergeInto, pullFrom, milestoneId, dueDate, assignees);
}
}
private void createPullRequest(String prTitle, String prDescription, String mergeInto, String pullFrom, int milestoneId, String dueDate, List<String> assignees) {
CreatePullRequest createPullRequest = new CreatePullRequest(prTitle, prDescription, loginUid, mergeInto, pullFrom, milestoneId, dueDate, assignees, labelsIds);
Call<ResponseBody> transferCall = RetrofitClient
.getApiInterface(appCtx)
.createPullRequest(instanceToken, repoOwner, repoName, createPullRequest);
transferCall.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
disableProcessButton();
if (response.code() == 201) {
Toasty.success(ctx, getString(R.string.prCreateSuccess));
finish();
}
else if (response.code() == 409 && response.message().equals("Conflict")) {
enableProcessButton();
Toasty.error(ctx, getString(R.string.prAlreadyExists));
}
else if (response.code() == 404) {
enableProcessButton();
Toasty.error(ctx, getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
}
@Override
public void labelsInterface(List<String> data) {
labelsSetter = String.valueOf(data);
viewBinding.prLabels.setText(labelsSetter.replace("]", "").replace("[", ""));
}
@Override
public void labelsIdsInterface(List<Integer> data) {
labelsIds = data;
}
private void showLabels() {
dialogLabels = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogLabels.getWindow() != null) {
dialogLabels.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
labelsBinding = CustomLabelsSelectionDialogBinding.inflate(LayoutInflater.from(ctx));
View view = labelsBinding.getRoot();
dialogLabels.setContentView(view);
labelsBinding.cancel.setOnClickListener(editProperties -> dialogLabels.dismiss());
dialogLabels.show();
LabelsActions.getRepositoryLabels(ctx, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
}
private void getBranches(String repoOwner, String repoName) {
Call<List<Branches>> call = RetrofitClient
.getApiInterface(ctx)
.getBranches(Authorization.get(ctx), repoOwner, repoName);
call.enqueue(new Callback<List<Branches>>() {
@Override
public void onResponse(@NonNull Call<List<Branches>> call, @NonNull retrofit2.Response<List<Branches>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Branches> branchesList_ = response.body();
assert branchesList_ != null;
if(branchesList_.size() > 0) {
for (int i = 0; i < branchesList_.size(); i++) {
Branches data = new Branches(branchesList_.get(i).getName());
branchesList.add(data);
}
}
ArrayAdapter<Branches> adapter = new ArrayAdapter<>(CreatePullRequestActivity.this,
R.layout.list_spinner_items, branchesList);
viewBinding.mergeIntoBranchSpinner.setAdapter(adapter);
viewBinding.pullFromBranchSpinner.setAdapter(adapter);
enableProcessButton();
}
}
}
@Override
public void onFailure(@NonNull Call<List<Branches>> call, @NonNull Throwable t) {
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
}
private void getMilestones(String repoOwner, String repoName, int resultLimit) {
String msState = "open";
Call<List<Milestones>> call = RetrofitClient
.getApiInterface(appCtx)
.getMilestones(Authorization.get(ctx), repoOwner, repoName, 1, resultLimit, msState);
call.enqueue(new Callback<List<Milestones>>() {
@Override
public void onResponse(@NonNull Call<List<Milestones>> call, @NonNull retrofit2.Response<List<Milestones>> response) {
if(response.code() == 200) {
List<Milestones> milestonesList_ = response.body();
milestonesList.add(new Milestones(0,getString(R.string.issueCreatedNoMilestone)));
assert milestonesList_ != null;
if(milestonesList_.size() > 0) {
for (int i = 0; i < milestonesList_.size(); i++) {
//Don't translate "open" is a enum
if(milestonesList_.get(i).getState().equals("open")) {
Milestones data = new Milestones(
milestonesList_.get(i).getId(),
milestonesList_.get(i).getTitle()
);
milestonesList.add(data);
}
}
}
ArrayAdapter<Milestones> adapter = new ArrayAdapter<>(CreatePullRequestActivity.this,
R.layout.list_spinner_items, milestonesList);
viewBinding.milestonesSpinner.setAdapter(adapter);
enableProcessButton();
viewBinding.milestonesSpinner.setOnItemClickListener ((parent, view, position, id) ->
milestoneId = milestonesList.get(position).getId()
);
}
}
@Override
public void onFailure(@NonNull Call<List<Milestones>> call, @NonNull Throwable t) {
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
}
private void setDueDate() {
final Calendar c = Calendar.getInstance();
int mYear = c.get(Calendar.YEAR);
final int mMonth = c.get(Calendar.MONTH);
final int mDay = c.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(this,
(view, year, monthOfYear, dayOfMonth) -> viewBinding.prDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth)), mYear, mMonth, mDay);
datePickerDialog.show();
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void disableProcessButton() {
viewBinding.createPr.setEnabled(false);
}
private void enableProcessButton() {
viewBinding.createPr.setEnabled(true);
}
}

View File

@ -1,33 +1,31 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.Releases;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
@ -38,14 +36,16 @@ public class CreateReleaseActivity extends BaseActivity {
private View.OnClickListener onClickListener;
public ImageView closeActivity;
private EditText releaseTagName;
private Spinner releaseBranch;
private AutoCompleteTextView releaseBranch;
private EditText releaseTitle;
private EditText releaseContent;
private CheckBox releaseType;
private CheckBox releaseDraft;
private Button createNewRelease;
final Context ctx = this;
private Context appCtx;
private String selectedBranch;
private String repoOwner;
private String repoName;
List<Branches> branchesList = new ArrayList<>();
@ -54,24 +54,20 @@ public class CreateReleaseActivity extends BaseActivity {
return R.layout.activity_create_release;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
repoOwner = parts[0];
repoName = parts[1];
closeActivity = findViewById(R.id.close);
releaseTagName = findViewById(R.id.releaseTagName);
@ -80,27 +76,26 @@ public class CreateReleaseActivity extends BaseActivity {
releaseType = findViewById(R.id.releaseType);
releaseDraft = findViewById(R.id.releaseDraft);
releaseTagName.requestFocus();
releaseTitle.requestFocus();
assert imm != null;
imm.showSoftInput(releaseTagName, InputMethodManager.SHOW_IMPLICIT);
imm.showSoftInput(releaseTitle, InputMethodManager.SHOW_IMPLICIT);
releaseContent.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
releaseBranch = findViewById(R.id.releaseBranch);
releaseBranch.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
getBranches(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
releaseBranch.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Branches branch = (Branches) parent.getSelectedItem();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
getBranches(Authorization.get(ctx), repoOwner, repoName);
createNewRelease = findViewById(R.id.createNewRelease);
disableProcessButton();
@ -108,76 +103,63 @@ public class CreateReleaseActivity extends BaseActivity {
if(!connToInternet) {
disableProcessButton();
} else {
}
else {
createNewRelease.setOnClickListener(createReleaseListener);
}
}
private View.OnClickListener createReleaseListener = new View.OnClickListener() {
public void onClick(View v) {
processNewRelease();
}
};
private final View.OnClickListener createReleaseListener = v -> processNewRelease();
private void processNewRelease() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newReleaseTagName = releaseTagName.getText().toString();
String newReleaseTitle = releaseTitle.getText().toString();
String newReleaseContent = releaseContent.getText().toString();
String newReleaseBranch = releaseBranch.getSelectedItem().toString();
String checkBranch = selectedBranch;
boolean newReleaseType = releaseType.isChecked();
boolean newReleaseDraft = releaseDraft.isChecked();
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newReleaseTitle.equals("")) {
Toasty.error(ctx, getString(R.string.titleErrorEmpty));
return;
}
if(newReleaseTagName.equals("")) {
Toasty.info(ctx, getString(R.string.tagNameErrorEmpty));
Toasty.error(ctx, getString(R.string.tagNameErrorEmpty));
return;
}
if(newReleaseTitle.equals("")) {
if(checkBranch == null) {
Toasty.info(ctx, getString(R.string.titleErrorEmpty));
return;
}
Toasty.error(ctx, getString(R.string.selectBranchError));
return;
}
disableProcessButton();
createNewReleaseFunc(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, newReleaseTagName, newReleaseTitle, newReleaseContent, newReleaseBranch, newReleaseType, newReleaseDraft);
createNewReleaseFunc(Authorization.get(ctx), repoOwner, repoName, newReleaseTagName, newReleaseTitle, newReleaseContent, selectedBranch, newReleaseType, newReleaseDraft);
}
private void createNewReleaseFunc(final String instanceUrl, final String token, String repoOwner, String repoName, String newReleaseTagName, String newReleaseTitle, String newReleaseContent, String newReleaseBranch, boolean newReleaseType, boolean newReleaseDraft) {
private void createNewReleaseFunc(final String token, String repoOwner, String repoName, String newReleaseTagName, String newReleaseTitle, String newReleaseContent, String selectedBranch, boolean newReleaseType, boolean newReleaseDraft) {
Releases createReleaseJson = new Releases(newReleaseContent, newReleaseDraft, newReleaseTitle, newReleaseType, newReleaseTagName, newReleaseBranch);
Releases createReleaseJson = new Releases(newReleaseContent, newReleaseDraft, newReleaseTitle, newReleaseType, newReleaseTagName, selectedBranch);
Call<Releases> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.createNewRelease(token, repoOwner, repoName, createReleaseJson);
call.enqueue(new Callback<Releases>() {
@ -187,12 +169,10 @@ public class CreateReleaseActivity extends BaseActivity {
if (response.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx);
tinyDb.putBoolean("updateReleases", true);
Toasty.info(ctx, getString(R.string.releaseCreatedText));
tinyDB.putBoolean("updateReleases", true);
Toasty.success(ctx, getString(R.string.releaseCreatedText));
enableProcessButton();
finish();
}
else if(response.code() == 401) {
@ -201,31 +181,27 @@ public class CreateReleaseActivity extends BaseActivity {
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.genericError));
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Releases> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -233,11 +209,10 @@ public class CreateReleaseActivity extends BaseActivity {
}
private void getBranches(String instanceUrl, String instanceToken, final String repoOwner, final String repoName) {
private void getBranches(String instanceToken, final String repoOwner, final String repoName) {
Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.getBranches(instanceToken, repoOwner, repoName);
call.enqueue(new Callback<List<Branches>>() {
@ -246,29 +221,27 @@ public class CreateReleaseActivity extends BaseActivity {
public void onResponse(@NonNull Call<List<Branches>> call, @NonNull retrofit2.Response<List<Branches>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Branches> branchesList_ = response.body();
assert branchesList_ != null;
if(branchesList_.size() > 0) {
for (int i = 0; i < branchesList_.size(); i++) {
Branches data = new Branches(
branchesList_.get(i).getName()
);
branchesList.add(data);
}
branchesList.addAll(branchesList_);
}
ArrayAdapter<Branches> adapter = new ArrayAdapter<>(CreateReleaseActivity.this,
R.layout.spinner_item, branchesList);
ArrayAdapter<Branches> adapter = new ArrayAdapter<>(CreateReleaseActivity.this,
R.layout.list_spinner_items, branchesList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
releaseBranch.setAdapter(adapter);
enableProcessButton();
releaseBranch.setOnItemClickListener ((parent, view, position, id) ->
selectedBranch = branchesList.get(position).getName()
);
}
}
else if(response.code() == 401) {
@ -277,13 +250,13 @@ public class CreateReleaseActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
}
@Override
public void onFailure(@NonNull Call<List<Branches>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
@ -291,32 +264,18 @@ public class CreateReleaseActivity extends BaseActivity {
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
private void disableProcessButton() {
createNewRelease.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewRelease.setBackground(shape);
}
private void enableProcessButton() {
createNewRelease.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createNewRelease.setBackground(shape);
}
}

View File

@ -1,29 +1,28 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import androidx.annotation.NonNull;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.OrgOwner;
import org.mian.gitnex.models.OrganizationRepository;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -39,15 +38,18 @@ public class CreateRepoActivity extends BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
private Spinner spinner;
private AutoCompleteTextView spinner;
private Button createRepo;
private EditText repoName;
private EditText repoDesc;
private CheckBox repoAccess;
final Context ctx = this;
private Context appCtx;
List<OrgOwner> organizationsList = new ArrayList<>();
private String loginUid;
private String userLogin;
private String selectedOwner;
List<OrgOwner> organizationsList = new ArrayList<>();
//https://github.com/go-gitea/gitea/blob/52cfd2743c0e85b36081cf80a850e6a5901f1865/models/repo.go#L964-L967
final List<String> reservedRepoNames = Arrays.asList(".", "..");
@ -62,15 +64,11 @@ public class CreateRepoActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(ctx);
boolean connToInternet = AppUtil.hasNetworkConnection(ctx);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String userLogin = tinyDb.getString("userLogin");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
loginUid = tinyDB.getString("loginUid");
userLogin = tinyDB.getString("userLogin");
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -87,19 +85,7 @@ public class CreateRepoActivity extends BaseActivity {
closeActivity.setOnClickListener(onClickListener);
spinner = findViewById(R.id.ownerSpinner);
spinner.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
getOrganizations(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), userLogin);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
OrgOwner user = (OrgOwner) parent.getSelectedItem();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
getOrganizations(Authorization.get(ctx), userLogin);
createRepo = findViewById(R.id.createNewRepoButton);
disableProcessButton();
@ -107,99 +93,82 @@ public class CreateRepoActivity extends BaseActivity {
if(!connToInternet) {
disableProcessButton();
}
else {
createRepo.setOnClickListener(createRepoListener);
}
}
private View.OnClickListener createRepoListener = new View.OnClickListener() {
public void onClick(View v) {
processNewRepo();
}
};
private final View.OnClickListener createRepoListener = v -> processNewRepo();
private void processNewRepo() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String newRepoName = repoName.getText().toString();
String newRepoDesc = repoDesc.getText().toString();
String repoOwner = spinner.getSelectedItem().toString();
boolean newRepoAccess = repoAccess.isChecked();
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(!newRepoDesc.equals("")) {
if (appUtil.charactersLength(newRepoDesc) > 255) {
Toasty.info(ctx, getString(R.string.repoDescError));
Toasty.warning(ctx, getString(R.string.repoDescError));
return;
}
}
if(newRepoName.equals("")) {
Toasty.info(ctx, getString(R.string.repoNameErrorEmpty));
Toasty.error(ctx, getString(R.string.repoNameErrorEmpty));
}
else if(!appUtil.checkStrings(newRepoName)) {
Toasty.info(ctx, getString(R.string.repoNameErrorInvalid));
Toasty.warning(ctx, getString(R.string.repoNameErrorInvalid));
}
else if (reservedRepoNames.contains(newRepoName)) {
Toasty.info(ctx, getString(R.string.repoNameErrorReservedName));
Toasty.warning(ctx, getString(R.string.repoNameErrorReservedName));
}
else if (reservedRepoPatterns.matcher(newRepoName).find()) {
Toasty.info(ctx, getString(R.string.repoNameErrorReservedPatterns));
Toasty.warning(ctx, getString(R.string.repoNameErrorReservedPatterns));
}
else if(selectedOwner == null) {
Toasty.error(ctx, getString(R.string.repoOwnerError));
}
else {
disableProcessButton();
createNewRepository(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), loginUid, newRepoName, newRepoDesc, repoOwner, newRepoAccess);
createNewRepository(Authorization.get(ctx), loginUid, newRepoName, newRepoDesc, selectedOwner, newRepoAccess);
}
}
private void createNewRepository(final String instanceUrl, final String token, String loginUid, String repoName, String repoDesc, String repoOwner, boolean isPrivate) {
private void createNewRepository(final String token, String loginUid, String repoName, String repoDesc, String selectedOwner, boolean isPrivate) {
OrganizationRepository createRepository = new OrganizationRepository(true, repoDesc, null, null, repoName, isPrivate, "Default");
Call<OrganizationRepository> call;
if(repoOwner.equals(loginUid)) {
if(selectedOwner.equals(loginUid)) {
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.createNewUserRepository(token, createRepository);
}
else {
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.createNewUserOrgRepository(token, repoOwner, createRepository);
.getApiInterface(ctx)
.createNewUserOrgRepository(token, selectedOwner, createRepository);
}
call.enqueue(new Callback<OrganizationRepository>() {
@ -209,9 +178,9 @@ public class CreateRepoActivity extends BaseActivity {
if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
tinyDb.putBoolean("repoCreated", true);
Toasty.info(ctx, getString(R.string.repoCreated));
Toasty.success(ctx, getString(R.string.repoCreated));
enableProcessButton();
finish();
}
@ -222,38 +191,32 @@ public class CreateRepoActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 409) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.repoExistsError));
Toasty.warning(ctx, getString(R.string.repoExistsError));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.repoCreatedError));
Toasty.error(ctx, getString(R.string.repoCreatedError));
}
}
@Override
public void onFailure(@NonNull Call<OrganizationRepository> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void getOrganizations(String instanceUrl, String instanceToken, final String userLogin) {
TinyDB tinyDb = new TinyDB(appCtx);
private void getOrganizations(String instanceToken, final String userLogin) {
Call<List<OrgOwner>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(ctx)
.getOrgOwners(instanceToken);
call.enqueue(new Callback<List<OrgOwner>>() {
@ -261,60 +224,63 @@ public class CreateRepoActivity extends BaseActivity {
@Override
public void onResponse(@NonNull Call<List<OrgOwner>> call, @NonNull retrofit2.Response<List<OrgOwner>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
if(response.code() == 200) {
int organizationId = 0;
int organizationId = 0;
List<OrgOwner> organizationsList_ = response.body();
List<OrgOwner> organizationsList_ = response.body();
organizationsList.add(new OrgOwner(userLogin));
assert organizationsList_ != null;
if(organizationsList_.size() > 0) {
for (int i = 0; i < organizationsList_.size(); i++) {
organizationsList.add(new OrgOwner(userLogin));
assert organizationsList_ != null;
if(!tinyDb.getString("organizationId").isEmpty()) {
if (Integer.parseInt(tinyDb.getString("organizationId")) == organizationsList_.get(i).getId()) {
organizationId = i + 1;
}
}
OrgOwner data = new OrgOwner(
organizationsList_.get(i).getUsername()
);
organizationsList.add(data);
if(organizationsList_.size() > 0) {
}
}
for(int i = 0; i < organizationsList_.size(); i++) {
ArrayAdapter<OrgOwner> adapter = new ArrayAdapter<>(CreateRepoActivity.this,
R.layout.spinner_item, organizationsList);
if(!tinyDB.getString("organizationId").isEmpty()) {
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
spinner.setAdapter(adapter);
if(Integer.parseInt(tinyDB.getString("organizationId")) == organizationsList_.get(i).getId()) {
organizationId = i + 1;
}
}
if (tinyDb.getBoolean("organizationAction") & organizationId != 0) {
spinner.setSelection(organizationId);
tinyDb.putBoolean("organizationAction", false);
}
OrgOwner data = new OrgOwner(organizationsList_.get(i).getUsername());
organizationsList.add(data);
}
}
enableProcessButton();
ArrayAdapter<OrgOwner> adapter = new ArrayAdapter<>(CreateRepoActivity.this, R.layout.list_spinner_items, organizationsList);
}
}
else if(response.code() == 401) {
spinner.setAdapter(adapter);
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
spinner.setOnItemClickListener ((parent, view, position, id) -> selectedOwner = organizationsList.get(position).getUsername());
}
if(tinyDB.getBoolean("organizationAction") & organizationId != 0) {
int selectOwnerById = organizationId;
new Handler(Looper.getMainLooper()).postDelayed(() -> {
spinner.setText(organizationsList.get(selectOwnerById).getUsername(), false);
selectedOwner = organizationsList.get(selectOwnerById).getUsername();
}, 500);
tinyDB.putBoolean("organizationAction", false);
}
enableProcessButton();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
}
@Override
public void onFailure(@NonNull Call<List<OrgOwner>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -322,32 +288,18 @@ public class CreateRepoActivity extends BaseActivity {
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
private void disableProcessButton() {
createRepo.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createRepo.setBackground(shape);
}
private void enableProcessButton() {
createRepo.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createRepo.setBackground(shape);
}
}

View File

@ -1,30 +1,29 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Teams;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.util.Log;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
@ -32,8 +31,6 @@ import android.util.Log;
public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClickListener {
final Context ctx = CreateTeamByOrgActivity.this;
private Context appCtx;
private View.OnClickListener onClickListener;
private TextView teamName;
private TextView teamDesc;
@ -42,7 +39,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
private TextView teamAccessControls;
private TextView teamAccessControlsArray;
private Button createTeamButton;
private String[] permissionList = {"Read", "Write", "Admin"};
private final String[] permissionList = {"Read", "Write", "Admin"};
public int permissionSelectedChoice = -1;
@Override
@ -50,7 +47,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
return R.layout.activity_create_team_by_org;
}
private String[] accessControlsList = new String[] {
private final String[] accessControlsList = new String[] {
"Code",
"Issues",
"Pull Request",
@ -62,7 +59,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
private List<String> pushAccessList;
private boolean[] selectedAccessControlsTrueFalse = new boolean[]{
private final boolean[] selectedAccessControlsTrueFalse = new boolean[]{
false,
false,
false,
@ -76,9 +73,8 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -98,134 +94,115 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
teamPermission.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
teamPermission.setOnClickListener(view -> {
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx);
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx);
pBuilder.setTitle(R.string.newTeamPermission);
if(permissionSelectedChoice != -1) {
pBuilder.setCancelable(true);
}
else {
pBuilder.setCancelable(false);
}
pBuilder.setSingleChoiceItems(permissionList, permissionSelectedChoice, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
pBuilder.setTitle(R.string.newTeamPermission);
pBuilder.setCancelable(permissionSelectedChoice != -1);
permissionSelectedChoice = i;
teamPermission.setText(permissionList[i]);
pBuilder.setSingleChoiceItems(permissionList, permissionSelectedChoice, (dialogInterface, i) -> {
if(permissionList[i].equals("Read")) {
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionRead);
permissionSelectedChoice = i;
teamPermission.setText(permissionList[i]);
switch(permissionList[i]) {
case "Read":
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionRead);
break;
case "Write":
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionWrite);
break;
case "Admin":
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionAdmin);
break;
default:
teamPermissionDetail.setVisibility(View.GONE);
break;
}
dialogInterface.dismiss();
});
AlertDialog pDialog = pBuilder.create();
pDialog.show();
});
teamAccessControls.setOnClickListener(v -> {
teamAccessControls.setText("");
teamAccessControlsArray.setText("");
pushAccessList = Arrays.asList(accessControlsList);
AlertDialog.Builder aDialogBuilder = new AlertDialog.Builder(ctx);
aDialogBuilder.setMultiChoiceItems(accessControlsList, selectedAccessControlsTrueFalse, (dialog, which, isChecked) -> {
})
.setCancelable(false)
.setTitle(R.string.newTeamAccessControls)
.setPositiveButton(R.string.okButton, (dialog, which) -> {
int selectedVal = 0;
while(selectedVal < selectedAccessControlsTrueFalse.length)
{
boolean value = selectedAccessControlsTrueFalse[selectedVal];
String repoCode = "";
if(selectedVal == 0) {
repoCode = "repo.code";
}
else if(permissionList[i].equals("Write")) {
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionWrite);
if(selectedVal == 1) {
repoCode = "repo.issues";
}
else if(permissionList[i].equals("Admin")) {
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionAdmin);
if(selectedVal == 2) {
repoCode = "repo.pulls";
}
else {
teamPermissionDetail.setVisibility(View.GONE);
if(selectedVal == 3) {
repoCode = "repo.releases";
}
if(selectedVal == 4) {
repoCode = "repo.wiki";
}
if(selectedVal == 5) {
repoCode = "repo.ext_wiki";
}
if(selectedVal == 6) {
repoCode = "repo.ext_issues";
}
dialogInterface.dismiss();
if(value){
teamAccessControls.setText(getString(R.string.newTeamPermissionValues, teamAccessControls.getText(), pushAccessList.get(selectedVal)));
teamAccessControlsArray.setText(getString(R.string.newTeamPermissionValuesFinal, teamAccessControlsArray.getText(), repoCode));
}
selectedVal++;
}
String data = String.valueOf(teamAccessControls.getText());
if(!data.equals("")) {
teamAccessControls.setText(data.substring(0, data.length() - 2));
}
String dataArray = String.valueOf(teamAccessControlsArray.getText());
if(!dataArray.equals("")) {
teamAccessControlsArray.setText(dataArray.substring(0, dataArray.length() - 2));
}
});
AlertDialog pDialog = pBuilder.create();
pDialog.show();
}
});
teamAccessControls.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
teamAccessControls.setText("");
teamAccessControlsArray.setText("");
pushAccessList = Arrays.asList(accessControlsList);
AlertDialog.Builder aDialogBuilder = new AlertDialog.Builder(ctx);
aDialogBuilder.setMultiChoiceItems(accessControlsList, selectedAccessControlsTrueFalse, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
}
})
.setCancelable(false)
.setTitle(R.string.newTeamAccessControls)
.setPositiveButton(R.string.okButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int selectedVal = 0;
while(selectedVal < selectedAccessControlsTrueFalse.length)
{
boolean value = selectedAccessControlsTrueFalse[selectedVal];
String repoCode = "";
if(selectedVal == 0) {
repoCode = "repo.code";
}
if(selectedVal == 1) {
repoCode = "repo.issues";
}
if(selectedVal == 2) {
repoCode = "repo.pulls";
}
if(selectedVal == 3) {
repoCode = "repo.releases";
}
if(selectedVal == 4) {
repoCode = "repo.wiki";
}
if(selectedVal == 5) {
repoCode = "repo.ext_wiki";
}
if(selectedVal == 6) {
repoCode = "repo.ext_issues";
}
if(value){
teamAccessControls.setText(getString(R.string.newTeamPermissionValues, teamAccessControls.getText(), pushAccessList.get(selectedVal)));
teamAccessControlsArray.setText(getString(R.string.newTeamPermissionValuesFinal, teamAccessControlsArray.getText(), repoCode));
}
selectedVal++;
}
String data = String.valueOf(teamAccessControls.getText());
if(!data.equals("")) {
teamAccessControls.setText(data.substring(0, data.length() - 2));
}
String dataArray = String.valueOf(teamAccessControlsArray.getText());
if(!dataArray.equals("")) {
teamAccessControlsArray.setText(dataArray.substring(0, dataArray.length() - 2));
}
//Log.i("orgName", String.valueOf(teamAccessControlsArray.getText()));
}
});
AlertDialog aDialog = aDialogBuilder.create();
aDialog.show();
}
AlertDialog aDialog = aDialogBuilder.create();
aDialog.show();
});
createTeamButton.setEnabled(false);
@ -237,26 +214,23 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createTeamButton.setBackground(shape);
} else {
}
else {
createTeamButton.setEnabled(true);
createTeamButton.setOnClickListener(this);
}
}
private void processCreateTeam() {
AppUtil appUtil = new AppUtil();
final TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final String orgName = tinyDb.getString("orgName");;
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newTeamName = teamName.getText().toString();
String newTeamDesc = teamDesc.getText().toString();
String newTeamPermission = teamPermission.getText().toString().toLowerCase();
@ -264,66 +238,62 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (newTeamName.equals("")) {
Toasty.info(ctx, getString(R.string.teamNameEmpty));
Toasty.error(ctx, getString(R.string.teamNameEmpty));
return;
}
if(!appUtil.checkStringsWithAlphaNumericDashDotUnderscore(newTeamName)) {
Toasty.info(ctx, getString(R.string.teamNameError));
Toasty.warning(ctx, getString(R.string.teamNameError));
return;
}
if(!newTeamDesc.equals("")) {
if(!appUtil.checkStrings(newTeamDesc)) {
Toasty.info(ctx, getString(R.string.teamDescError));
Toasty.warning(ctx, getString(R.string.teamDescError));
return;
}
if(newTeamDesc.length() > 100) {
Toasty.info(ctx, getString(R.string.teamDescLimit));
Toasty.warning(ctx, getString(R.string.teamDescLimit));
return;
}
}
if (newTeamPermission.equals("")) {
Toasty.info(ctx, getString(R.string.teamPermissionEmpty));
Toasty.error(ctx, getString(R.string.teamPermissionEmpty));
return;
}
List<String> newTeamAccessControls_ = new ArrayList<>(Arrays.asList(newTeamAccessControls.split(",")));
for (int i = 0; i < newTeamAccessControls_.size(); i++) {
newTeamAccessControls_.set(i, newTeamAccessControls_.get(i).trim());
}
createNewTeamCall(instanceUrl, instanceToken, orgName, newTeamName, newTeamDesc, newTeamPermission, newTeamAccessControls_, loginUid);
createNewTeamCall(instanceToken, orgName, newTeamName, newTeamDesc, newTeamPermission, newTeamAccessControls_, loginUid);
}
private void createNewTeamCall(final String instanceUrl, final String instanceToken, String orgName, String newTeamName, String newTeamDesc, String newTeamPermission, List<String> newTeamAccessControls, String loginUid) {
private void createNewTeamCall(final String instanceToken, String orgName, String newTeamName, String newTeamDesc, String newTeamPermission, List<String> newTeamAccessControls, String loginUid) {
Teams createNewTeamJson = new Teams(newTeamName, newTeamDesc, newTeamPermission, newTeamAccessControls);
Call<Teams> call3;
call3 = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.createTeamsByOrg(Authorization.returnAuthentication(ctx, loginUid, instanceToken), orgName, createNewTeamJson);
.getApiInterface(ctx)
.createTeamsByOrg(Authorization.get(ctx), orgName, createNewTeamJson);
call3.enqueue(new Callback<Teams>() {
@ -331,21 +301,19 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
public void onResponse(@NonNull Call<Teams> call, @NonNull retrofit2.Response<Teams> response2) {
if(response2.isSuccessful()) {
if(response2.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
tinyDb.putBoolean("resumeTeams", true);
Toasty.info(ctx, getString(R.string.teamCreated));
Toasty.success(ctx, getString(R.string.teamCreated));
finish();
}
}
else if(response2.code() == 404) {
Toasty.info(ctx, getString(R.string.apiNotFound));
Toasty.warning(ctx, getString(R.string.apiNotFound));
}
else if(response2.code() == 401) {
@ -353,14 +321,11 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.info(ctx, getString(R.string.teamCreatedError));
Toasty.error(ctx, getString(R.string.teamCreatedError));
}
}
@Override
@ -373,19 +338,16 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
@Override
public void onClick(View v) {
if(v == createTeamButton) {
processCreateTeam();
}
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
}

View File

@ -1,68 +0,0 @@
package org.mian.gitnex.activities;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.CreditsAdapter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Author M M Arif
*/
public class CreditsActivity extends BaseActivity {
private View.OnClickListener onClickListener;
final Context ctx = this;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_credits;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ImageView closeActivity = findViewById(R.id.close);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
Resources res = getResources();
CharSequence[] creditsInfo = res.getTextArray(R.array.creditsInfo);
List<CharSequence> creditsList = new ArrayList<>(Arrays.asList(creditsInfo));
RecyclerView mRecyclerView = findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(ctx));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
CreditsAdapter adapter = new CreditsAdapter(creditsList);
mRecyclerView.setAdapter(adapter);
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}

View File

@ -0,0 +1,455 @@
package org.mian.gitnex.activities;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.databinding.ActivityDeeplinksBinding;
import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.models.PullRequests;
import org.mian.gitnex.models.UserRepositories;
import java.net.URI;
import java.util.List;
import java.util.Objects;
import io.mikael.urlbuilder.UrlBuilder;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class DeepLinksActivity extends BaseActivity {
private ActivityDeeplinksBinding viewBinding;
private String currentInstance;
private String instanceToken;
private boolean accountFound = false;
private Intent mainIntent;
private Intent issueIntent;
private Intent repoIntent;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_deeplinks;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewBinding = ActivityDeeplinksBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
mainIntent = new Intent(ctx, MainActivity.class);
issueIntent = new Intent(ctx, IssueDetailActivity.class);
repoIntent = new Intent(ctx, RepoDetailActivity.class);
Intent intent = getIntent();
Uri data = intent.getData();
assert data != null;
// check for login
if(!tinyDB.getBoolean("loggedInMode")) {
finish();
ctx.startActivity(new Intent(ctx, LoginActivity.class));
}
// check for the links(URI) to be in the db
UserAccountsApi userAccountsApi = new UserAccountsApi(ctx);
List<UserAccount> userAccounts = userAccountsApi.usersAccounts();
for(UserAccount userAccount : userAccounts) {
String hostUri = userAccount.getInstanceUrl();
currentInstance = userAccount.getInstanceUrl();
instanceToken = userAccount.getToken();
if(hostUri.toLowerCase().contains(Objects.requireNonNull(data.getHost().toLowerCase()))) {
accountFound = true;
break;
}
}
if(accountFound) {
// redirect to proper fragment/activity, If no action is there, show options where user to want to go like repos, profile, notifications etc
if(data.getPathSegments().size() > 0) {
viewBinding.progressBar.setVisibility(View.GONE);
String[] restOfUrl = Objects.requireNonNull(data.getPath()).split("/");
if(data.getPathSegments().contains("issues")) { // issue
if(!Objects.requireNonNull(data.getLastPathSegment()).contains("issues") & StringUtils.isNumeric(data.getLastPathSegment())) {
issueIntent.putExtra("issueNumber", data.getLastPathSegment());
tinyDB.putString("issueNumber", data.getLastPathSegment());
tinyDB.putString("issueType", "Issue");
tinyDB.putString("repoFullName", restOfUrl[restOfUrl.length - 4] + "/" + restOfUrl[restOfUrl.length - 3]);
final String repoOwner = restOfUrl[restOfUrl.length - 4];
final String repoName = restOfUrl[restOfUrl.length - 3];
int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDB.putLong("repositoryId", id);
}
else {
Repository dataRepo = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDB.putLong("repositoryId", dataRepo.getRepositoryId());
}
ctx.startActivity(issueIntent);
finish();
}
else if(Objects.requireNonNull(data.getLastPathSegment()).contains("issues")) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 3], restOfUrl[restOfUrl.length - 2], "issue");
}, 500);
}
else {
ctx.startActivity(mainIntent);
finish();
}
}
else if(data.getPathSegments().contains("pulls")) { // pr
if(!Objects.requireNonNull(data.getLastPathSegment()).contains("pulls") & StringUtils.isNumeric(data.getLastPathSegment())) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
getPullRequest(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 4], restOfUrl[restOfUrl.length - 3], Integer.parseInt(data.getLastPathSegment()));
}, 500);
}
else if(Objects.requireNonNull(data.getLastPathSegment()).contains("pulls")) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 3], restOfUrl[restOfUrl.length - 2], "pull");
}, 500);
}
else {
ctx.startActivity(mainIntent);
finish();
}
}
else if(data.getPathSegments().contains("commit")) { // commits (no API yet to properly implement)
new Handler(Looper.getMainLooper()).postDelayed(() -> {
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 4], restOfUrl[restOfUrl.length - 3], "pull");
}, 500);
}
else if(!restOfUrl[restOfUrl.length - 2].equals("") & !restOfUrl[restOfUrl.length - 1].equals("")) { // go to repo
new Handler(Looper.getMainLooper()).postDelayed(() -> {
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 2], restOfUrl[restOfUrl.length - 1], "repo");
}, 500);
}
else { // no action, show options
if(tinyDB.getInt("defaultScreenId") == 1) { // repos
mainIntent.putExtra("launchFragmentByLinkHandler", "repos");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDB.getInt("defaultScreenId") == 2) { // org
mainIntent.putExtra("launchFragmentByLinkHandler", "org");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDB.getInt("defaultScreenId") == 3) { // notifications
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 {
startActivity(mainIntent);
finish();
}
}
else {
viewBinding.progressBar.setVisibility(View.GONE);
viewBinding.addNewAccountFrame.setVisibility(View.VISIBLE);
viewBinding.noActionFrame.setVisibility(View.GONE);
viewBinding.addAccountText.setText(String.format(getResources().getString(R.string.accountDoesNotExist), data.getHost()));
viewBinding.addNewAccount.setOnClickListener(addNewAccount -> {
Intent accountIntent = new Intent(ctx, AddNewAccountActivity.class);
startActivity(accountIntent);
finish();
});
viewBinding.openInBrowser.setOnClickListener(addNewAccount -> {
Integer port = data.getPort() >= 0 ? data.getPort() : null;
URI host = UrlBuilder.fromString(UrlHelper.fixScheme(data.getHost(), "https"))
.withPort(port)
.toUri();
Intent intentBrowser = new Intent();
intentBrowser.setAction(Intent.ACTION_VIEW);
intentBrowser.addCategory(Intent.CATEGORY_BROWSABLE);
intentBrowser.setData(Uri.parse(String.valueOf(host)));
startActivity(intentBrowser);
finish();
});
viewBinding.launchApp.setOnClickListener(launchApp -> {
startActivity(mainIntent);
finish();
});
}
}
private void getPullRequest(String url, String token, String repoOwner, String repoName, int index) {
Call<PullRequests> call = RetrofitClient
.getApiInterface(ctx, url)
.getPullRequestByIndex(token, repoOwner, repoName, index);
call.enqueue(new Callback<PullRequests>() {
@Override
public void onResponse(@NonNull Call<PullRequests> call, @NonNull retrofit2.Response<PullRequests> response) {
PullRequests prInfo = response.body();
if (response.code() == 200) {
assert prInfo != null;
issueIntent.putExtra("issueNumber", index);
issueIntent.putExtra("prMergeable", prInfo.isMergeable());
if(prInfo.getHead() != null) {
issueIntent.putExtra("prHeadBranch", prInfo.getHead().getRef());
tinyDB.putString("prHeadBranch", prInfo.getHead().getRef());
if(prInfo.getHead().getRepo() != null) {
tinyDB.putString("prIsFork", String.valueOf(prInfo.getHead().getRepo().isFork()));
tinyDB.putString("prForkFullName", prInfo.getHead().getRepo().getFull_name());
}
else {
// pull was done from a deleted fork
tinyDB.putString("prIsFork", "true");
tinyDB.putString("prForkFullName", ctx.getString(R.string.prDeletedFrok));
}
}
tinyDB.putString("issueNumber", String.valueOf(index));
tinyDB.putString("prMergeable", String.valueOf(prInfo.isMergeable()));
tinyDB.putString("issueType", "Pull");
tinyDB.putString("repoFullName", repoOwner + "/" + repoName);
int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDB.putLong("repositoryId", id);
}
else {
Repository dataRepo = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDB.putLong("repositoryId", dataRepo.getRepositoryId());
}
ctx.startActivity(issueIntent);
finish();
}
else {
ctx.startActivity(issueIntent);
finish();
Log.e("onFailure-links-pr", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<PullRequests> call, @NonNull Throwable t) {
ctx.startActivity(issueIntent);
finish();
Log.e("onFailure-links-pr", t.toString());
}
});
}
private void goToRepoSection(String url, String token, String repoOwner, String repoName, String type) {
Call<UserRepositories> call = RetrofitClient
.getApiInterface(ctx, url)
.getUserRepository(token, repoOwner, repoName);
call.enqueue(new Callback<UserRepositories>() {
@Override
public void onResponse(@NonNull Call<UserRepositories> call, @NonNull retrofit2.Response<UserRepositories> response) {
UserRepositories repoInfo = response.body();
if (response.code() == 200) {
assert repoInfo != null;
repoIntent.putExtra("repoFullName", repoInfo.getFullName());
repoIntent.putExtra("goToSection", "yes");
repoIntent.putExtra("goToSectionType", type);
tinyDB.putString("repoFullName", repoInfo.getFullName());
if(repoInfo.getPrivateFlag()) {
tinyDB.putString("repoType", getResources().getString(R.string.strPrivate));
}
else {
tinyDB.putString("repoType", getResources().getString(R.string.strPublic));
}
tinyDB.putBoolean("isRepoAdmin", repoInfo.getPermissions().isAdmin());
tinyDB.putString("repoBranch", repoInfo.getDefault_branch());
int currentActiveAccountId = tinyDB.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDB.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDB.putLong("repositoryId", data.getRepositoryId());
}
ctx.startActivity(repoIntent);
finish();
}
else {
ctx.startActivity(mainIntent);
finish();
Log.e("onFailure-goToRepo", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) {
ctx.startActivity(mainIntent);
finish();
Log.e("onFailure-goToRepo", t.toString());
}
});
}
}

View File

@ -1,47 +1,41 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.CreateIssue;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
@ -49,45 +43,46 @@ import java.util.List;
public class EditIssueActivity extends BaseActivity implements View.OnClickListener {
final Context ctx = this;
private Context appCtx;
private View.OnClickListener onClickListener;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private EditText editIssueTitle;
private SocialAutoCompleteTextView editIssueDescription;
private EditText editIssueDescription;
private TextView editIssueDueDate;
private Button editIssueButton;
private Spinner editIssueMilestoneSpinner;
private AutoCompleteTextView editIssueMilestoneSpinner;
private String msState = "open";
private int milestoneId;
List<Milestones> milestonesList = new ArrayList<>();
private ArrayAdapter<Mention> defaultMentionAdapter;
private String loginUid;
private String instanceToken;
private String repoOwner;
private String repoName;
private int issueIndex;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_edit_issue;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
final TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
loginUid = tinyDB.getString("loginUid");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
repoOwner = parts[0];
repoName = parts[1];
issueIndex = Integer.parseInt(tinyDB.getString("issueNumber"));
ImageView closeActivity = findViewById(R.id.close);
editIssueButton = findViewById(R.id.editIssueButton);
@ -97,7 +92,8 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
editIssueDueDate = findViewById(R.id.editIssueDueDate);
// 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;
}
@ -105,13 +101,18 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
assert imm != null;
imm.showSoftInput(editIssueTitle, InputMethodManager.SHOW_IMPLICIT);
defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList();
editIssueDescription.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
editIssueMilestoneSpinner = findViewById(R.id.editIssueMilestoneSpinner);
editIssueMilestoneSpinner.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
editIssueDescription.setMentionAdapter(defaultMentionAdapter);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
@ -119,97 +120,30 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
editIssueDueDate.setOnClickListener(this);
editIssueButton.setOnClickListener(this);
if(!tinyDb.getString("issueNumber").isEmpty()) {
if(!tinyDB.getString("issueNumber").isEmpty()) {
if(tinyDB.getString("issueType").equalsIgnoreCase("Pull")) {
if(tinyDb.getString("issueType").equals("pr")) {
toolbar_title.setText(getString(R.string.editPrNavHeader, String.valueOf(issueIndex)));
}
else {
toolbar_title.setText(getString(R.string.editIssueNavHeader, String.valueOf(issueIndex)));
}
}
disableProcessButton();
getIssue(instanceUrl, instanceToken, loginUid, repoOwner, repoName, issueIndex, resultLimit);
}
public void loadCollaboratorsList() {
final TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
String fullName = "";
for (int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(
new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
} else {
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.toString());
}
});
getIssue(instanceToken, loginUid, repoOwner, repoName, issueIndex, resultLimit);
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
private void processEditIssue() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
Milestones mModel = (Milestones) editIssueMilestoneSpinner.getSelectedItem();
int editIssueMilestoneId = mModel.getId();
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String editIssueTitleForm = editIssueTitle.getText().toString();
String editIssueDescriptionForm = editIssueDescription.getText().toString();
@ -217,47 +151,36 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (editIssueTitleForm.equals("")) {
Toasty.info(ctx, getString(R.string.issueTitleEmpty));
Toasty.error(ctx, getString(R.string.issueTitleEmpty));
return;
}
/*if (editIssueDescriptionForm.equals("")) {
Toasty.info(ctx, getString(R.string.issueDescriptionEmpty));
return;
}*/
if (editIssueDueDateForm.equals("")) {
editIssueDueDateForm = null;
} else {
}
else {
editIssueDueDateForm = (AppUtil.customDateCombine(AppUtil.customDateFormat(editIssueDueDateForm)));
}
//Log.i("editIssueDueDateForm", String.valueOf(editIssueDueDateForm));
disableProcessButton();
editIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid, editIssueTitleForm, editIssueDescriptionForm, editIssueDueDateForm, editIssueMilestoneId);
editIssue(instanceToken, repoOwner, repoName, issueIndex, loginUid, editIssueTitleForm, editIssueDescriptionForm, editIssueDueDateForm, milestoneId);
}
private void editIssue(String instanceUrl, String instanceToken, String repoOwner, String repoName, int issueIndex, String loginUid, String title, String description, String dueDate, int editIssueMilestoneId) {
private void editIssue(String instanceToken, String repoOwner, String repoName, int issueIndex, String loginUid, String title, String description, String dueDate, int milestoneId) {
final TinyDB tinyDb = new TinyDB(appCtx);
CreateIssue issueData = new CreateIssue(title, description, dueDate, editIssueMilestoneId);
CreateIssue issueData = new CreateIssue(title, description, dueDate, milestoneId);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.patchIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueData);
.getApiInterface(ctx)
.patchIssue(Authorization.get(ctx), repoOwner, repoName, issueIndex, issueData);
call.enqueue(new Callback<JsonElement>() {
@ -266,17 +189,18 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
if(response.code() == 201) {
if(tinyDb.getString("issueType").equals("pr")) {
Toasty.info(ctx, getString(R.string.editPrSuccessMessage));
if(tinyDB.getString("issueType").equalsIgnoreCase("Pull")) {
Toasty.success(ctx, getString(R.string.editPrSuccessMessage));
}
else {
Toasty.info(ctx, getString(R.string.editIssueSuccessMessage));
Toasty.success(ctx, getString(R.string.editIssueSuccessMessage));
}
tinyDb.putBoolean("issueEdited", true);
tinyDb.putBoolean("resumeIssues", true);
tinyDB.putBoolean("issueEdited", true);
tinyDB.putBoolean("resumeIssues", true);
finish();
}
else if(response.code() == 401) {
@ -285,19 +209,17 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -305,7 +227,6 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
}
@Override
public void onClick(View v) {
@ -317,31 +238,21 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
final int mDay = c.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(this,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
editIssueDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth));
}
}, mYear, mMonth, mDay);
(view, year, monthOfYear, dayOfMonth) -> editIssueDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth)), mYear, mMonth, mDay);
datePickerDialog.show();
}
else if(v == editIssueButton) {
processEditIssue();
}
}
private void getIssue(final String instanceUrl, final String instanceToken, final String loginUid, final String repoOwner, final String repoName, int issueIndex, int resultLimit) {
private void getIssue(final String instanceToken, final String loginUid, final String repoOwner, final String repoName, int issueIndex, int resultLimit) {
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex);
.getApiInterface(ctx)
.getIssueByIndex(Authorization.get(ctx), repoOwner, repoName, issueIndex);
call.enqueue(new Callback<Issues>() {
@ -354,27 +265,27 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
editIssueTitle.setText(response.body().getTitle());
editIssueDescription.setText(response.body().getBody());
int msId = 0;
int currentMilestoneId = 0;
if(response.body().getMilestone() != null) {
msId = response.body().getMilestone().getId();
currentMilestoneId = response.body().getMilestone().getId();
}
// get milestones list
if(response.body().getId() > 0) {
Call<List<Milestones>> call_ = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getMilestones(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, 1, resultLimit, msState);
.getApiInterface(ctx)
.getMilestones(Authorization.get(ctx), repoOwner, repoName, 1, resultLimit, msState);
final int finalMsId = msId;
int checkMilestoneId = currentMilestoneId;
call_.enqueue(new Callback<List<Milestones>>() {
call_.enqueue(new Callback<List<Milestones>>() {
@Override
public void onResponse(@NonNull Call<List<Milestones>> call, @NonNull retrofit2.Response<List<Milestones>> response_) {
int finalMsId1 = 0;
int getSelectedMilestoneId = 0;
if (response_.code() == 200) {
@ -382,39 +293,40 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
milestonesList.add(new Milestones(0, "No milestone"));
assert milestonesList_ != null;
if (milestonesList_.size() > 0) {
milestonesList.addAll(milestonesList_);
for (int i = 0; i < milestonesList_.size(); i++) {
Milestones data = new Milestones(
milestonesList_.get(i).getId(),
milestonesList_.get(i).getTitle()
);
milestonesList.add(data);
if(finalMsId == milestonesList_.get(i).getId()) {
finalMsId1 = i + 1;
if(checkMilestoneId == milestonesList_.get(i).getId()) {
getSelectedMilestoneId = i + 1;
}
}
}
ArrayAdapter<Milestones> adapter_ = new ArrayAdapter<>(EditIssueActivity.this,
R.layout.spinner_item, milestonesList);
ArrayAdapter<Milestones> adapter = new ArrayAdapter<>(EditIssueActivity.this,
R.layout.list_spinner_items, milestonesList);
adapter_.setDropDownViewResource(R.layout.spinner_dropdown_item);
editIssueMilestoneSpinner.setAdapter(adapter_);
editIssueMilestoneSpinner.setAdapter(adapter);
editIssueMilestoneSpinner.setOnItemClickListener ((parent, view, position, id) -> milestoneId = milestonesList.get(position).getId());
int finalMsId = getSelectedMilestoneId;
new Handler(Looper.getMainLooper()).postDelayed(() -> {
editIssueMilestoneSpinner.setText(milestonesList.get(finalMsId).getTitle(),false);
milestoneId = milestonesList.get(finalMsId).getId();
}, 500);
if(milestonesList_.size() > 0) {
editIssueMilestoneSpinner.setSelection(finalMsId1);
}
enableProcessButton();
}
}
@Override
public void onFailure(@NonNull Call<List<Milestones>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
@ -427,7 +339,6 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
@SuppressLint("SimpleDateFormat") DateFormat formatter = new SimpleDateFormat("yyyy-M-dd");
String dueDate = formatter.format(response.body().getDue_date());
editIssueDueDate.setText(dueDate);
}
//enableProcessButton();
@ -438,18 +349,16 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.info(ctx, getString(R.string.genericError));
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
@ -459,21 +368,11 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
private void disableProcessButton() {
editIssueButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
editIssueButton.setBackground(shape);
}
private void enableProcessButton() {
editIssueButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
editIssueButton.setBackground(shape);
}
}

View File

@ -1,6 +1,5 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
@ -10,17 +9,16 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import org.apache.commons.io.FileUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.FilesDiffAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.ParseDiff;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.FileDiffView;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
@ -32,191 +30,132 @@ import retrofit2.Callback;
public class FileDiffActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private TextView toolbar_title;
private ListView mListView;
private ProgressBar mProgressBar;
final Context ctx = this;
private Context appCtx;
private View.OnClickListener onClickListener;
private TextView toolbarTitle;
private ListView mListView;
private ProgressBar mProgressBar;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_file_diff;
}
@Override
protected int getLayoutResourceId() {
@Override
public void onCreate(Bundle savedInstanceState) {
return R.layout.activity_file_diff;
}
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
@Override
public void onCreate(Bundle savedInstanceState) {
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
super.onCreate(savedInstanceState);
final TinyDB tinyDb = new TinyDB(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ImageView closeActivity = findViewById(R.id.close);
toolbar_title = findViewById(R.id.toolbar_title);
mListView = findViewById(R.id.listView);
mProgressBar = findViewById(R.id.progress_bar);
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
mListView.setDivider(null);
ImageView closeActivity = findViewById(R.id.close);
toolbarTitle = findViewById(R.id.toolbar_title);
mListView = findViewById(R.id.listView);
mProgressBar = findViewById(R.id.progress_bar);
toolbar_title.setText(R.string.processingText);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
mListView.setDivider(null);
mProgressBar.setVisibility(View.VISIBLE);
toolbarTitle.setText(R.string.processingText);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
String pullIndex = tinyDb.getString("issueNumber");
mProgressBar.setVisibility(View.VISIBLE);
getPullDiffContent(tinyDb.getString("instanceUrlWithProtocol"), repoOwner, repoName, pullIndex);
String pullIndex = tinyDb.getString("issueNumber");
}
boolean apiCall = !new Version(tinyDb.getString("giteaVersion")).less("1.13.0");
getPullDiffContent(repoOwner, repoName, pullIndex, instanceToken, apiCall);
private void getPullDiffContent(String instanceUrl, String owner, String repo, String filename) {
}
Call<ResponseBody> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getWebInterface()
.getPullDiffContent(owner, repo, filename);
private void getPullDiffContent(String owner, String repo, String pullIndex, String token, boolean apiCall) {
call.enqueue(new Callback<ResponseBody>() {
Call<ResponseBody> call;
if(apiCall) {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
call = RetrofitClient.getApiInterface(ctx).getPullDiffContent(token, owner, repo, pullIndex);
}
else {
if (response.code() == 200) {
call = RetrofitClient.getWebInterface(ctx).getPullDiffContent(owner, repo, pullIndex);
}
try {
assert response.body() != null;
call.enqueue(new Callback<ResponseBody>() {
AppUtil appUtil = new AppUtil();
List<FileDiffView> fileContentsArray = new ArrayList<>();
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
String[] lines = response.body().string().split("diff");
if(response.code() == 200) {
if(lines.length > 0) {
try {
for (int i = 1; i < lines.length; i++) {
assert response.body() != null;
if(lines[i].contains("@@ -")) {
List<FileDiffView> fileContentsArray = ParseDiff.getFileDiffViewArray(response.body().string());
String[] level2nd = lines[i].split("@@ -"); // main content part of single diff view
int filesCount = fileContentsArray.size();
if(filesCount > 1) {
String[] fileName_ = level2nd[0].split("\\+\\+\\+ b/"); // filename part
String fileNameFinal = fileName_[1];
toolbarTitle.setText(getResources().getString(R.string.fileDiffViewHeader, Integer.toString(filesCount)));
}
else {
String[] fileContents_ = level2nd[1].split("@@"); // file info / content part
String fileInfoFinal = fileContents_[0];
StringBuilder fileContentsFinal = new StringBuilder(fileContents_[1]);
toolbarTitle.setText(getResources().getString(R.string.fileDiffViewHeaderSingle, Integer.toString(filesCount)));
}
if(level2nd.length > 2) {
for (int j = 2; j < level2nd.length; j++) {
fileContentsFinal.append(level2nd[j]);
}
}
FilesDiffAdapter adapter = new FilesDiffAdapter(ctx, getSupportFragmentManager(), fileContentsArray);
mListView.setAdapter(adapter);
String fileExtension = FileUtils.getExtension(fileNameFinal);
mProgressBar.setVisibility(View.GONE);
}
catch(IOException e) {
String fileContentsFinalWithBlankLines = fileContentsFinal.toString().replaceAll( ".*@@.*", "" );
String fileContentsFinalWithoutBlankLines = fileContentsFinal.toString().replaceAll( ".*@@.*(\r?\n|\r)?", "" );
fileContentsFinalWithoutBlankLines = fileContentsFinalWithoutBlankLines.replaceAll( ".*\\ No newline at end of file.*(\r?\n|\r)?", "" );
e.printStackTrace();
}
}
else if(response.code() == 401) {
fileContentsArray.add(new FileDiffView(fileNameFinal, appUtil.imageExtension(fileExtension), fileInfoFinal, fileContentsFinalWithoutBlankLines));
}
else {
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) {
String[] getFileName = lines[i].split("--git a/");
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
String[] getFileName_ = getFileName[1].split("b/");
String getFileNameFinal = getFileName_[0].trim();
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
String[] binaryFile = getFileName_[1].split("GIT binary patch");
String binaryFileRaw = binaryFile[1].substring(binaryFile[1].indexOf('\n')+1);
String binaryFileFinal = binaryFile[1].substring(binaryFileRaw.indexOf('\n')+1);
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
String fileExtension = FileUtils.getExtension(getFileNameFinal);
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
if(appUtil.imageExtension(FileUtils.getExtension(getFileNameFinal))) {
Log.e("onFailure", t.toString());
}
});
fileContentsArray.add(new FileDiffView(getFileNameFinal, appUtil.imageExtension(fileExtension), "", binaryFileFinal));
}
}
}
private void initCloseListener() {
}
}
int filesCount = fileContentsArray.size();
if(filesCount > 1) {
toolbar_title.setText(getResources().getString(R.string.fileDiffViewHeader, Integer.toString(filesCount)));
}
else {
toolbar_title.setText(getResources().getString(R.string.fileDiffViewHeaderSingle, Integer.toString(filesCount)));
}
FilesDiffAdapter adapter = new FilesDiffAdapter(ctx, fileContentsArray);
mListView.setAdapter(adapter);
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.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
getIntent().removeExtra("singleFileName");
finish();
}
};
}
onClickListener = view -> {
getIntent().removeExtra("singleFileName");
finish();
};
}
}

View File

@ -1,6 +1,6 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.app.Activity;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Typeface;
@ -20,8 +20,11 @@ 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.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.util.FitPolicy;
@ -31,12 +34,12 @@ import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BottomSheetFileViewerFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.highlightjs.HighlightJsView;
import org.mian.gitnex.helpers.highlightjs.models.Theme;
import org.mian.gitnex.models.Files;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
@ -57,14 +60,15 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
private LinearLayout singleFileContentsFrame;
private HighlightJsView singleCodeContents;
private PhotoView imageView;
final Context ctx = this;
private Context appCtx;
private ProgressBar mProgressBar;
private byte[] imageData;
private PDFView pdfView;
private LinearLayout pdfViewFrame;
private byte[] decodedPdf;
private Boolean pdfNightMode;
private String singleFileName;
private String fileSha;
private AppUtil appUtil;
@Override
protected int getLayoutResourceId() {
@ -76,19 +80,20 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
appUtil = new AppUtil();
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final TinyDB tinyDb = new TinyDB(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
String repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final String loginUid = tinyDB.getString("loginUid");
final String instanceToken = "token " + tinyDB.getString(loginUid + "-token");
tinyDB.putBoolean("enableMarkdownInFileView", false);
ImageView closeActivity = findViewById(R.id.close);
singleFileContents = findViewById(R.id.singleFileContents);
@ -99,7 +104,7 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
pdfViewFrame = findViewById(R.id.pdfViewFrame);
singleFileContentsFrame = findViewById(R.id.singleFileContentsFrame);
String singleFileName = getIntent().getStringExtra("singleFileName");
singleFileName = getIntent().getStringExtra("singleFileName");
TextView toolbar_title = findViewById(R.id.toolbar_title);
toolbar_title.setMovementMethod(new ScrollingMovementMethod());
@ -107,33 +112,48 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
tinyDb.putString("downloadFileContents", "");
tinyDB.putString("downloadFileContents", "");
try {
singleFileName = URLDecoder.decode(singleFileName, "UTF-8");
singleFileName = singleFileName.replaceAll("//", "/");
singleFileName = singleFileName.startsWith("/") ? singleFileName.substring(1) : singleFileName;
}
catch(UnsupportedEncodingException e) {
assert singleFileName != null;
Log.i("singleFileName", singleFileName);
}
toolbar_title.setText(singleFileName);
getSingleFileContents(instanceUrl, instanceToken, repoOwner, repoName, singleFileName);
getSingleFileContents(instanceToken, repoOwner, repoName, singleFileName, repoBranch);
}
private void getSingleFileContents(String instanceUrl, String token, final String owner, String repo, final String filename) {
@Override
public void onResume() {
final TinyDB tinyDb = new TinyDB(appCtx);
super.onResume();
Call<Files> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getSingleFileContents(token, owner, repo, filename);
String repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
String loginUid = tinyDB.getString("loginUid");
String instanceToken = "token " + tinyDB.getString(loginUid + "-token");
if(tinyDB.getBoolean("fileModified")) {
getSingleFileContents(instanceToken, repoOwner, repoName, singleFileName, repoBranch);
tinyDB.putBoolean("fileModified", false);
}
}
private void getSingleFileContents(String token, final String owner, String repo, final String filename, String ref) {
Call<Files> call = RetrofitClient.getApiInterface(ctx).getSingleFileContents(token, owner, repo, filename, ref);
call.enqueue(new Callback<Files>() {
@ -142,7 +162,6 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
if(response.code() == 200) {
AppUtil appUtil = new AppUtil();
assert response.body() != null;
if(!response.body().getContent().equals("")) {
@ -150,9 +169,11 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
String fileExtension = FileUtils.getExtension(filename);
mProgressBar.setVisibility(View.GONE);
fileSha = response.body().getSha();
// download file meta
tinyDb.putString("downloadFileName", filename);
tinyDb.putString("downloadFileContents", response.body().getContent());
tinyDB.putString("downloadFileName", filename);
tinyDB.putString("downloadFileContents", response.body().getContent());
if(appUtil.imageExtension(fileExtension)) { // file is image
@ -164,7 +185,6 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
imageData = Base64.decode(response.body().getContent(), Base64.DEFAULT);
Drawable imageDrawable = new BitmapDrawable(getResources(), BitmapFactory.decodeByteArray(imageData, 0, imageData.length));
imageView.setImageDrawable(imageDrawable);
}
else if(appUtil.sourceCodeExtension(fileExtension)) { // file is sourcecode
@ -173,28 +193,34 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
pdfViewFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.VISIBLE);
switch(tinyDb.getInt("fileviewerSourceCodeThemeId")) {
switch(tinyDB.getInt("fileviewerSourceCodeThemeId")) {
case 1:
singleCodeContents.setTheme(Theme.ARDUINO_LIGHT);
break;
case 2:
singleCodeContents.setTheme(Theme.GITHUB);
break;
case 3:
singleCodeContents.setTheme(Theme.FAR);
break;
case 4:
singleCodeContents.setTheme(Theme.IR_BLACK);
break;
case 5:
singleCodeContents.setTheme(Theme.ANDROID_STUDIO);
break;
default:
singleCodeContents.setTheme(Theme.MONOKAI_SUBLIME);
}
singleCodeContents.setSource(appUtil.decodeBase64(response.body().getContent()));
}
else if(appUtil.pdfExtension(fileExtension)) { // file is pdf
@ -203,7 +229,7 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.VISIBLE);
pdfNightMode = tinyDb.getBoolean("enablePdfMode");
pdfNightMode = tinyDB.getBoolean("enablePdfMode");
decodedPdf = Base64.decode(response.body().getContent(), Base64.DEFAULT);
pdfView.fromBytes(decodedPdf).enableSwipe(true).swipeHorizontal(false).enableDoubletap(true).defaultPage(0).enableAnnotationRendering(false).password(null).scrollHandle(null).enableAntialiasing(true).spacing(0).autoSpacing(true).pageFitPolicy(FitPolicy.WIDTH).fitEachPage(true).pageSnap(false).pageFling(true).nightMode(pdfNightMode).load();
@ -219,7 +245,6 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
singleFileContents.setText(getResources().getString(R.string.excludeFilesInFileviewer));
singleFileContents.setGravity(Gravity.CENTER);
singleFileContents.setTypeface(null, Typeface.BOLD);
}
else { // file type not known - plain text view
@ -229,37 +254,30 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setText(appUtil.decodeBase64(response.body().getContent()));
}
}
else {
singleFileContents.setText("");
mProgressBar.setVisibility(View.GONE);
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(ctx, getString(R.string.labelGeneralError));
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
@ -276,6 +294,15 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
inflater.inflate(R.menu.files_view_menu, menu);
String fileExtension = FileUtils.getExtension(singleFileName);
if(!fileExtension.equalsIgnoreCase("md")) {
menu.getItem(0).setVisible(false);
}
return true;
}
@ -284,18 +311,42 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
int id = item.getItemId();
switch(id) {
case android.R.id.home:
finish();
return true;
case R.id.genericMenu:
BottomSheetFileViewerFragment bottomSheet = new BottomSheetFileViewerFragment();
bottomSheet.show(getSupportFragmentManager(), "fileViewerBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
if(id == android.R.id.home) {
finish();
return true;
}
else if(id == R.id.genericMenu) {
BottomSheetFileViewerFragment bottomSheet = new BottomSheetFileViewerFragment();
bottomSheet.show(getSupportFragmentManager(), "fileViewerBottomSheet");
return true;
}
else if(id == R.id.markdown) {
new Markdown(ctx, appUtil.decodeBase64(tinyDB.getString("downloadFileContents")), singleFileContents);
if(!tinyDB.getBoolean("enableMarkdownInFileView")) {
singleCodeContents.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setVisibility(View.VISIBLE);
tinyDB.putBoolean("enableMarkdownInFileView", true);
}
else {
singleCodeContents.setVisibility(View.VISIBLE);
singleFileContentsFrame.setVisibility(View.GONE);
singleFileContents.setVisibility(View.GONE);
singleCodeContents.setSource(appUtil.decodeBase64(tinyDB.getString("downloadFileContents")));
tinyDB.putBoolean("enableMarkdownInFileView", false);
}
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
@Override
@ -304,20 +355,57 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
if("downloadFile".equals(text)) {
requestFileDownload();
}
if("deleteFile".equals(text)) {
String fileExtension = FileUtils.getExtension(singleFileName);
String data = appUtil.decodeBase64(tinyDB.getString("downloadFileContents"));
Intent intent = new Intent(ctx, CreateFileActivity.class);
intent.putExtra("fileAction", 1);
intent.putExtra("filePath", singleFileName);
intent.putExtra("fileSha", fileSha);
if(!appUtil.imageExtension(fileExtension)) {
intent.putExtra("fileContents", data);
}
else {
intent.putExtra("fileContents", "");
}
ctx.startActivity(intent);
}
if("editFile".equals(text)) {
String fileExtension = FileUtils.getExtension(singleFileName);
String data = appUtil.decodeBase64(tinyDB.getString("downloadFileContents"));
Intent intent = new Intent(ctx, CreateFileActivity.class);
intent.putExtra("fileAction", 2);
intent.putExtra("filePath", singleFileName);
intent.putExtra("fileSha", fileSha);
if(!appUtil.imageExtension(fileExtension)) {
intent.putExtra("fileContents", data);
}
else {
intent.putExtra("fileContents", "");
}
ctx.startActivity(intent);
}
}
private void requestFileDownload() {
final TinyDB tinyDb = new TinyDB(appCtx);
if(!tinyDB.getString("downloadFileContents").isEmpty()) {
if(!tinyDb.getString("downloadFileContents").isEmpty()) {
int CREATE_REQUEST_CODE = 40;
File outputFileName = new File(tinyDb.getString("downloadFileName"));
File outputFileName = new File(tinyDB.getString("downloadFileName"));
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
@ -325,48 +413,48 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_TITLE, outputFileName.getName());
startActivityForResult(intent, CREATE_REQUEST_CODE);
fileDownloadActivityResultLauncher.launch(intent);
}
else {
Toasty.error(ctx, getString(R.string.waitLoadingDownloadFile));
}
Toasty.warning(ctx, getString(R.string.waitLoadingDownloadFile));
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
ActivityResultLauncher<Intent> fileDownloadActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
super.onActivityResult(requestCode, resultCode, data);
@Override
public void onActivityResult(ActivityResult result) {
final TinyDB tinyDb = new TinyDB(appCtx);
if (result.getResultCode() == Activity.RESULT_OK) {
if (requestCode == 40 && resultCode == RESULT_OK) {
Intent data = result.getData();
try {
try {
assert data != null;
Uri uri = data.getData();
assert data != null;
Uri uri = data.getData();
assert uri != null;
OutputStream outputStream = getContentResolver().openOutputStream(uri);
assert uri != null;
OutputStream outputStream = getContentResolver().openOutputStream(uri);
byte[] dataAsBytes = Base64.decode(tinyDb.getString("downloadFileContents"), 0);
byte[] dataAsBytes = Base64.decode(tinyDB.getString("downloadFileContents"), 0);
assert outputStream != null;
outputStream.write(dataAsBytes);
outputStream.close();
assert outputStream != null;
outputStream.write(dataAsBytes);
outputStream.close();
Toasty.info(ctx, getString(R.string.downloadFileSaved));
Toasty.success(ctx, getString(R.string.downloadFileSaved));
}
catch(IOException e) {
Log.e("errorFileDownloading", Objects.requireNonNull(e.getMessage()));
}
}
catch (IOException e) {
Log.e("errorFileDownloading", Objects.requireNonNull(e.getMessage()));
}
}
}
});
private void initCloseListener() {
@ -374,8 +462,7 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
getIntent().removeExtra("singleFileName");
finish();
};
}
}
}

View File

@ -1,50 +1,65 @@
package org.mian.gitnex.activities;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.navigation.NavigationView;
import com.squareup.picasso.NetworkPolicy;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.UserAccountsNavAdapter;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.AboutFragment;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.fragments.AdministrationFragment;
import org.mian.gitnex.fragments.ExploreRepositoriesFragment;
import org.mian.gitnex.fragments.BottomSheetDraftsFragment;
import org.mian.gitnex.fragments.DraftsFragment;
import org.mian.gitnex.fragments.ExploreFragment;
import org.mian.gitnex.fragments.MyRepositoriesFragment;
import org.mian.gitnex.fragments.NotificationsFragment;
import org.mian.gitnex.fragments.OrganizationsFragment;
import org.mian.gitnex.fragments.ProfileFragment;
import org.mian.gitnex.fragments.RepositoriesFragment;
import org.mian.gitnex.fragments.SettingsFragment;
import org.mian.gitnex.fragments.StarredRepositoriesFragment;
import org.mian.gitnex.fragments.UserAccountsFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.ChangeLog;
import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.models.NotificationCount;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import eightbitlab.com.blurview.BlurView;
import eightbitlab.com.blurview.RenderScriptBlur;
import retrofit2.Call;
import retrofit2.Callback;
@ -52,17 +67,25 @@ import retrofit2.Callback;
* Author M M Arif
*/
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener {
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener, BottomSheetDraftsFragment.BottomSheetListener {
private DrawerLayout drawer;
private BlurView blurView;
private TextView userFullName;
private TextView userEmail;
private ImageView userAvatar;
private ImageView userAvatarBackground;
private ViewGroup navHeaderFrame;
private TextView toolbarTitle;
final Context ctx = this;
private Context appCtx;
private Typeface myTypeface;
private String loginUid;
private String instanceToken;
private View hView;
private MenuItem navNotifications;
private TextView notificationCounter;
@Override
protected int getLayoutResourceId() {
@ -73,57 +96,69 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
final TinyDB tinyDb = new TinyDB(appCtx);
tinyDb.putBoolean("noConnection", false);
//userAvatar = findViewById(R.id.userAvatar);
tinyDB.putBoolean("noConnection", false);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String currentVersion = tinyDB.getString("giteaVersion");
if(tinyDb.getString("dateFormat").isEmpty()) {
tinyDb.putString("dateFormat", "pretty");
Intent mainIntent = getIntent();
String launchFragment = mainIntent.getStringExtra("launchFragment");
loginUid = tinyDB.getString("loginUid");
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("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("enableCounterIssueBadgeInit").isEmpty()) {
tinyDB.putBoolean("enableCounterIssueBadge", true);
}
if(tinyDb.getString("homeScreenStr").isEmpty()) {
tinyDb.putInt("homeScreenId", 0);
if(tinyDB.getString("homeScreenStr").isEmpty()) {
tinyDB.putString("homeScreenStr", "yes");
tinyDB.putInt("homeScreenId", 0);
}
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
if(!tinyDB.getBoolean("loggedInMode")) {
if(!tinyDb.getBoolean("loggedInMode")) {
logout(this, ctx);
return;
}
if(tinyDB.getInt("currentActiveAccountId") <= 0) {
AlertDialogs.forceLogoutDialog(ctx, getResources().getString(R.string.forceLogoutDialogHeader), getResources().getString(R.string.forceLogoutDialogDescription), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
Toolbar toolbar = findViewById(R.id.toolbar);
toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
switch(tinyDb.getInt("customFontId", -1)) {
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/manroperegular.ttf");
break;
}
toolbarTitle.setTypeface(myTypeface);
@ -131,269 +166,490 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
FragmentManager fm = getSupportFragmentManager();
Fragment fragmentById = fm.findFragmentById(R.id.fragment_container);
if(fragmentById instanceof SettingsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
}
else if(fragmentById instanceof MyRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
}
else if(fragmentById instanceof StarredRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
}
else if(fragmentById instanceof OrganizationsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
}
else if(fragmentById instanceof ExploreRepositoriesFragment) {
else if(fragmentById instanceof ExploreFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
}
else if(fragmentById instanceof NotificationsFragment) {
toolbarTitle.setText(R.string.pageTitleNotifications);
}
else if(fragmentById instanceof ProfileFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
}
else if(fragmentById instanceof AboutFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout));
else if(fragmentById instanceof DraftsFragment) {
toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
}
else if(fragmentById instanceof AdministrationFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
}
else if(fragmentById instanceof UserAccountsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleUserAccounts));
}
getNotificationsCount(instanceToken);
drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
final View hView = navigationView.getHeaderView(0);
hView = navigationView.getHeaderView(0);
Menu menu = navigationView.getMenu();
navNotifications = menu.findItem(R.id.nav_notifications);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
toggle.getDrawerArrowDrawable().setColor(getResources().getColor(R.color.darkGreen));
drawer.addDrawerListener(toggle);
drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
}
@Override
public void onDrawerOpened(@NonNull View drawerView) {
if(tinyDb.getBoolean("noConnection")) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
tinyDb.putBoolean("noConnection", false);
if(tinyDB.getBoolean("noConnection")) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
tinyDB.putBoolean("noConnection", false);
}
String userEmailNav = tinyDb.getString("userEmail");
String userFullNameNav = tinyDb.getString("userFullname");
String userAvatarNav = tinyDb.getString("userAvatar");
String userEmailNav = tinyDB.getString("userEmail");
String userFullNameNav = tinyDB.getString("userFullname");
String userAvatarNav = tinyDB.getString("userAvatar");
blurView = hView.findViewById(R.id.blurView);
userEmail = hView.findViewById(R.id.userEmail);
if(!userEmailNav.equals("")) {
userEmail.setText(userEmailNav);
userEmail.setTypeface(myTypeface);
}
userFullName = hView.findViewById(R.id.userFullname);
if(!userFullNameNav.equals("")) {
userFullName.setText(userFullNameNav);
userFullName.setTypeface(myTypeface);
}
userAvatar = hView.findViewById(R.id.userAvatar);
if(!userAvatarNav.equals("")) {
PicassoService.getInstance(ctx).get().load(userAvatarNav).networkPolicy(NetworkPolicy.OFFLINE).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(160, 160).centerCrop().into(userAvatar);
}
userAvatarBackground = hView.findViewById(R.id.userAvatarBackground);
navHeaderFrame = hView.findViewById(R.id.navHeaderFrame);
userAvatar.setOnClickListener(new View.OnClickListener() {
List<UserAccount> userAccountsList;
userAccountsList = new ArrayList<>();
UserAccountsApi userAccountsApi;
userAccountsApi = new UserAccountsApi(ctx);
public void onClick(View v) {
RecyclerView navRecyclerViewUserAccounts = hView.findViewById(R.id.navRecyclerViewUserAccounts);
UserAccountsNavAdapter adapterUserAccounts;
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
drawer.closeDrawers();
adapterUserAccounts = new UserAccountsNavAdapter(ctx, userAccountsList, drawer, toolbarTitle);
userAccountsApi.getAllAccounts().observe((AppCompatActivity) ctx, userAccounts -> {
if(userAccounts.size() > 0) {
userAccountsList.addAll(userAccounts);
navRecyclerViewUserAccounts.setAdapter(adapterUserAccounts);
}
});
userEmail.setTypeface(myTypeface);
userFullName.setTypeface(myTypeface);
if(!userEmailNav.equals("")) {
userEmail.setText(userEmailNav);
}
if(!userFullNameNav.equals("")) {
userFullName.setText(userFullNameNav);
}
if(!userAvatarNav.equals("")) {
PicassoService.getInstance(ctx).get()
.load(userAvatarNav)
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(8, 0))
.resize(160, 160)
.centerCrop().into(userAvatar);
PicassoService.getInstance(ctx).get()
.load(userAvatarNav)
.into(userAvatarBackground, new com.squareup.picasso.Callback() {
@Override
public void onSuccess() {
int textColor = new ColorInverter().getImageViewContrastColor(userAvatarBackground);
userFullName.setTextColor(textColor);
userEmail.setTextColor(textColor);
blurView.setupWith(navHeaderFrame)
.setBlurAlgorithm(new RenderScriptBlur(ctx))
.setBlurRadius(5)
.setHasFixedTransformationMatrix(false);
}
@Override
public void onError(Exception e) {}
});
}
userAvatar.setOnClickListener(v -> {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
drawer.closeDrawers();
});
getNotificationsCount(instanceToken);
}
@Override
public void onDrawerClosed(@NonNull View drawerView) {
// Called when a drawer has settled in a completely closed state.
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
navigationView.getMenu().findItem(R.id.nav_administration).setVisible(tinyDB.getBoolean("userIsAdmin"));
navigationView.getMenu().findItem(R.id.nav_notifications).setVisible(new Version(currentVersion).higherOrEqual("1.12.3"));
}
@Override
public void onDrawerStateChanged(int newState) {
// Called when the drawer motion state changes. The new state will be one of STATE_IDLE, STATE_DRAGGING or STATE_SETTLING.
}
public void onDrawerClosed(@NonNull View drawerView) {}
@Override
public void onDrawerStateChanged(int newState) {}
});
toggle.syncState();
toolbar.setNavigationIcon(R.drawable.ic_menu);
if(launchFragment != null) {
mainIntent.removeExtra("launchFragment");
switch(launchFragment) {
case "drafts":
toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_comments_draft);
return;
case "notifications":
toolbarTitle.setText(getResources().getString(R.string.pageTitleNotifications));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications);
return;
}
}
String launchFragmentByHandler = mainIntent.getStringExtra("launchFragmentByLinkHandler");
if(launchFragmentByHandler != null) {
mainIntent.removeExtra("launchFragmentByLinkHandler");
switch(launchFragmentByHandler) {
case "repos":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories);
return;
case "org":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations);
return;
case "notification":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications);
return;
case "explore":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
navigationView.setCheckedItem(R.id.nav_explore);
return;
}
}
if(savedInstanceState == null) {
if(tinyDb.getInt("homeScreenId") == 0) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
if(!new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.3")) {
if(tinyDB.getInt("homeScreenId") == 7) {
tinyDB.putInt("homeScreenId", 0);
}
}
else if(tinyDb.getInt("homeScreenId") == 1) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_starred_repos);
}
else if(tinyDb.getInt("homeScreenId") == 2) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations);
}
else if(tinyDb.getInt("homeScreenId") == 3) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories);
}
else if(tinyDb.getInt("homeScreenId") == 4) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
}
else {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
switch(tinyDB.getInt("homeScreenId")) {
case 1:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_starred_repos);
break;
case 2:
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations);
break;
case 3:
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories);
break;
case 4:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
break;
case 5:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
navigationView.setCheckedItem(R.id.nav_explore);
break;
case 6:
toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_comments_draft);
break;
case 7:
toolbarTitle.setText(getResources().getString(R.string.pageTitleNotifications));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications);
break;
default:
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
break;
}
}
if(!connToInternet) {
if(!tinyDb.getBoolean("noConnection")) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
if(!tinyDB.getBoolean("noConnection")) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
}
tinyDb.putBoolean("noConnection", true);
tinyDB.putBoolean("noConnection", true);
}
else {
displayUserInfo(instanceUrl, instanceToken, loginUid);
giteaVersion(instanceUrl);
tinyDb.putBoolean("noConnection", false);
loadUserInfo(instanceToken, loginUid);
giteaVersion();
tinyDB.putBoolean("noConnection", false);
}
// Changelog popup
int versionCode = 0;
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")) {
tinyDb.putInt("versionCode", versionCode);
tinyDb.putBoolean("versionFlag", true);
if(versionCode > tinyDB.getInt("versionCode")) {
tinyDB.putInt("versionCode", versionCode);
tinyDB.putBoolean("versionFlag", true);
ChangeLog changelogDialog = new ChangeLog(this);
changelogDialog.showDialog();
}
}
public void setActionBarTitle(@NonNull String title) {
public void setActionBarTitle(String title) {
toolbarTitle.setText(title);
}
@Override
public void onButtonClicked(String text) {
TinyDB tinyDb = TinyDB.getInstance(ctx);
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
if("deleteDrafts".equals(text)) {
if(currentActiveAccountId > 0) {
FragmentManager fm = getSupportFragmentManager();
DraftsFragment frag = (DraftsFragment) fm.findFragmentById(R.id.fragment_container);
if(frag != null) {
new AlertDialog.Builder(ctx)
.setTitle(R.string.deleteAllDrafts)
.setIcon(R.drawable.ic_delete)
.setCancelable(false)
.setMessage(R.string.deleteAllDraftsDialogMessage)
.setPositiveButton(R.string.menuDeleteText, (dialog, which) -> {
frag.deleteAllDrafts(currentActiveAccountId);
dialog.dismiss();
})
.setNeutralButton(R.string.cancelButton, null).show();
}
else {
Toasty.error(ctx, getResources().getString(R.string.genericError));
}
}
else {
Toasty.error(ctx, getResources().getString(R.string.genericError));
}
}
Objects.requireNonNull(getSupportActionBar()).setTitle(title);
}
@Override
public void onBackPressed() {
if(drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
else {
super.onBackPressed();
}
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
switch(menuItem.getItemId()) {
case R.id.nav_home:
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
break;
case R.id.nav_organizations:
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
break;
case R.id.nav_profile:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
break;
case R.id.nav_repositories:
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
int id = menuItem.getItemId();
break;
case R.id.nav_settings:
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new SettingsFragment()).commit();
break;
case R.id.nav_logout:
logout(this, ctx);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
break;
case R.id.nav_about:
toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AboutFragment()).commit();
break;
case R.id.nav_rate_app:
rateThisApp();
break;
case R.id.nav_starred_repos:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
break;
case R.id.nav_explore:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreRepositoriesFragment()).commit();
break;
case R.id.nav_administration:
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AdministrationFragment()).commit();
break;
if(id == R.id.nav_home) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
}
else if(id == R.id.nav_organizations) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
}
else if(id == R.id.nav_profile) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
}
else if(id == R.id.nav_repositories) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
}
else if(id == R.id.nav_settings) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new SettingsFragment()).commit();
}
else if(id == R.id.nav_logout) {
logout(this, ctx);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
else if(id == R.id.nav_starred_repos) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
}
else if(id == R.id.nav_explore) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
}
else if(id == R.id.nav_notifications) {
toolbarTitle.setText(R.string.pageTitleNotifications);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
}
else if(id == R.id.nav_comments_draft) {
toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit();
}
else if(id == R.id.nav_administration) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AdministrationFragment()).commit();
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
public void rateThisApp() {
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName())));
}
catch(ActivityNotFoundException e) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName())));
}
}
public static void logout(Activity activity, Context ctx) {
TinyDB tinyDb = new TinyDB(ctx.getApplicationContext());
tinyDb.putBoolean("loggedInMode", false);
tinyDb.remove("basicAuthPassword");
tinyDb.putBoolean("basicAuthFlag", false);
TinyDB tinyDB = TinyDB.getInstance(ctx);
tinyDB.putBoolean("loggedInMode", false);
tinyDB.remove("basicAuthPassword");
tinyDB.putBoolean("basicAuthFlag", false);
//tinyDb.clear();
activity.finish();
ctx.startActivity(new Intent(ctx, LoginActivity.class));
}
private void giteaVersion(final String instanceUrl) {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
final TinyDB tinyDb = new TinyDB(appCtx);
int id = item.getItemId();
if(id == R.id.genericMenu) {
BottomSheetDraftsFragment bottomSheet = new BottomSheetDraftsFragment();
bottomSheet.show(getSupportFragmentManager(), "draftsBottomSheet");
return true;
}
return super.onOptionsItemSelected(item);
}
private void giteaVersion() {
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
Call<GiteaVersion> callVersion = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getGiteaVersionWithToken(token);
Call<GiteaVersion> callVersion = RetrofitClient.getApiInterface(ctx).getGiteaVersionWithToken(token);
callVersion.enqueue(new Callback<GiteaVersion>() {
@ -406,30 +662,22 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
assert version != null;
tinyDb.putString("giteaVersion", version.getVersion());
}
}
@Override
public void onFailure(@NonNull Call<GiteaVersion> callVersion, @NonNull Throwable t) {
Log.e("onFailure-version", t.toString());
}
});
}
private void displayUserInfo(String instanceUrl, String token, String loginUid) {
private void loadUserInfo(String token, String loginUid) {
final TinyDB tinyDb = new TinyDB(appCtx);
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
Call<UserInfo> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserInfo(Authorization.returnAuthentication(ctx, loginUid, token));
NavigationView navigationView = findViewById(R.id.nav_view);
final View hView = navigationView.getHeaderView(0);
Call<UserInfo> call = RetrofitClient.getApiInterface(ctx).getUserInfo(Authorization.get(ctx));
call.enqueue(new Callback<UserInfo>() {
@ -443,79 +691,46 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
if(response.code() == 200) {
assert userDetails != null;
if(userDetails.getIs_admin() != null) {
tinyDb.putBoolean("userIsAdmin", userDetails.getIs_admin());
navigationView.getMenu().findItem(R.id.nav_administration).setVisible(userDetails.getIs_admin());
}
tinyDb.putString("userLogin", userDetails.getLogin());
tinyDb.putInt("userId", userDetails.getId());
if(!userDetails.getFullname().equals("")) {
tinyDb.putString("userFullname", userDetails.getFullname());
}
else {
tinyDb.putString("userFullname", userDetails.getLogin());
}
tinyDb.putString("userEmail", userDetails.getEmail());
tinyDb.putString("userAvatar", userDetails.getAvatar());
if(userDetails.getLang() != null) {
tinyDb.putString("userLang", userDetails.getLang());
}
else {
tinyDb.putString("userLang", "...");
}
userAvatar = hView.findViewById(R.id.userAvatar);
if(!Objects.requireNonNull(userDetails).getAvatar().equals("")) {
PicassoService.getInstance(ctx).get().load(userDetails.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(160, 160).centerCrop().into(userAvatar);
tinyDb.putString("userLang", "");
}
else {
userAvatar.setImageResource(R.mipmap.app_logo_round);
}
userFullName = hView.findViewById(R.id.userFullname);
if(!userDetails.getFullname().equals("")) {
userFullName.setText(userDetails.getFullname());
}
else if(!userDetails.getLogin().equals("")) {
userFullName.setText(userDetails.getLogin());
}
else {
userFullName.setText("...");
}
userEmail = hView.findViewById(R.id.userEmail);
if(!userDetails.getEmail().equals("")) {
userEmail.setText(userDetails.getEmail());
}
else {
userEmail.setText("...");
}
userAvatar.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
drawer.closeDrawers();
}
});
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
String toastError = getResources().getString(R.string.genericApiStatusError) + String.valueOf(response.code());
Toasty.info(ctx, toastError);
String toastError = getResources().getString(R.string.genericApiStatusError) + response.code();
Toasty.error(ctx, toastError);
}
}
@Override
@ -527,4 +742,31 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
}
private void getNotificationsCount(String token) {
Call<NotificationCount> call = RetrofitClient.getApiInterface(ctx).checkUnreadNotifications(token);
call.enqueue(new Callback<NotificationCount>() {
@Override
public void onResponse(@NonNull Call<NotificationCount> call, @NonNull retrofit2.Response<NotificationCount> response) {
NotificationCount notificationCount = response.body();
if(response.code() == 200) {
assert notificationCount != null;
notificationCounter = navNotifications.getActionView().findViewById(R.id.counterBadgeNotification);
notificationCounter.setText(String.valueOf(notificationCount.getCounter()));
}
}
@Override
public void onFailure(@NonNull Call<NotificationCount> call, @NonNull Throwable t) {
Log.e("onFailure-notification", t.toString());
}
});
}
}

View File

@ -6,30 +6,24 @@ import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityMergePullRequestBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.MergePullRequest;
import org.mian.gitnex.models.MergePullRequestSpinner;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -38,11 +32,13 @@ import retrofit2.Response;
public class MergePullRequestActivity extends BaseActivity {
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private String repoOwner;
private String repoName;
private int prIndex;
private ActivityMergePullRequestBinding viewBinding;
private ArrayAdapter<Mention> defaultMentionAdapter;
private String Do;
@Override
@ -56,14 +52,18 @@ public class MergePullRequestActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
viewBinding = ActivityMergePullRequestBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx);
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repoOwner = parts[0];
repoName = parts[1];
prIndex = Integer.parseInt(tinyDB.getString("issueNumber"));
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -73,135 +73,72 @@ public class MergePullRequestActivity extends BaseActivity {
setMergeAdapter();
viewBinding.mergeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
if(!tinyDB.getString("issueTitle").isEmpty()) {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
MergePullRequestSpinner mergeId = (MergePullRequestSpinner) parent.getSelectedItem();
Do = mergeId.getId();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList();
viewBinding.mergeDescription.setMentionAdapter(defaultMentionAdapter);
if(!tinyDb.getString("issueTitle").isEmpty()) {
viewBinding.toolbarTitle.setText(tinyDb.getString("issueTitle"));
viewBinding.mergeTitle.setText(tinyDb.getString("issueTitle") + " (#" + tinyDb.getString("issueNumber") + ")");
viewBinding.toolbarTitle.setText(tinyDB.getString("issueTitle"));
viewBinding.mergeTitle.setText(tinyDB.getString("issueTitle") + " (#" + tinyDB.getString("issueNumber") + ")");
}
initCloseListener();
viewBinding.close.setOnClickListener(onClickListener);
// if gitea version is greater/equal(1.12.0) than user installed version (installed.higherOrEqual(compareVer))
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
viewBinding.deleteBranch.setVisibility(View.VISIBLE);
}
if(tinyDb.getString("prMergeable").equals("false")) {
if(tinyDB.getString("prMergeable").equals("false")) {
disableProcessButton();
viewBinding.mergeInfoDisabledMessage.setVisibility(View.VISIBLE);
}
else {
viewBinding.mergeInfoDisabledMessage.setVisibility(View.GONE);
}
if(tinyDb.getString("prIsFork").equals("true")) {
if(tinyDB.getString("prIsFork").equals("true")) {
viewBinding.deleteBranchForkInfo.setVisibility(View.VISIBLE);
}
else {
viewBinding.deleteBranchForkInfo.setVisibility(View.GONE);
}
if(!connToInternet) {
disableProcessButton();
}
else {
viewBinding.mergeButton.setOnClickListener(mergePullRequest);
}
}
private void setMergeAdapter() {
TinyDB tinyDb = new TinyDB(appCtx);
ArrayList<MergePullRequestSpinner> mergeList = new ArrayList<>();
mergeList.add(new MergePullRequestSpinner("merge", getResources().getString(R.string.mergeOptionMerge)));
mergeList.add(new MergePullRequestSpinner("rebase", getResources().getString(R.string.mergeOptionRebase)));
mergeList.add(new MergePullRequestSpinner("rebase-merge", getResources().getString(R.string.mergeOptionRebaseCommit)));
// squash merge works only on gitea > v1.11.4 due to a bug
if(new Version(tinyDb.getString("giteaVersion")).higher("1.11.4")) {
if(new Version(tinyDB.getString("giteaVersion")).higher("1.11.4")) {
mergeList.add(new MergePullRequestSpinner("squash", getResources().getString(R.string.mergeOptionSquash)));
}
ArrayAdapter<MergePullRequestSpinner> adapter = new ArrayAdapter<>(MergePullRequestActivity.this, R.layout.spinner_item, mergeList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
ArrayAdapter<MergePullRequestSpinner> adapter = new ArrayAdapter<>(MergePullRequestActivity.this, R.layout.list_spinner_items, mergeList);
viewBinding.mergeSpinner.setAdapter(adapter);
}
public void loadCollaboratorsList() {
final TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if(response.isSuccessful()) {
assert response.body() != null;
String fullName = "";
for(int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
}
else {
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.toString());
}
viewBinding.mergeSpinner.setOnItemClickListener ((parent, view, position, id) -> {
Do = mergeList.get(position).getId();
});
}
private void initCloseListener() {
@ -209,44 +146,38 @@ public class MergePullRequestActivity extends BaseActivity {
onClickListener = view -> finish();
}
private View.OnClickListener mergePullRequest = v -> processMergePullRequest();
private final View.OnClickListener mergePullRequest = v -> processMergePullRequest();
private void processMergePullRequest() {
String mergePRDesc = viewBinding.mergeDescription.getText().toString();
String mergePRTitle = viewBinding.mergeTitle.getText().toString();
String mergePRDesc = Objects.requireNonNull(viewBinding.mergeDescription.getText()).toString();
String mergePRTitle = Objects.requireNonNull(viewBinding.mergeTitle.getText()).toString();
boolean deleteBranch = viewBinding.deleteBranch.isChecked();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
disableProcessButton();
mergeFunction(Do, mergePRDesc, mergePRTitle, deleteBranch);
if(Do == null) {
Toasty.error(ctx, getResources().getString(R.string.selectMergeStrategy));
}
else {
disableProcessButton();
mergeFunction(Do, mergePRDesc, mergePRTitle, deleteBranch);
}
}
private void mergeFunction(String Do, String mergePRDT, String mergeTitle, boolean deleteBranch) {
final TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int prIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
MergePullRequest mergePR = new MergePullRequest(Do, mergePRDT, mergeTitle);
Call<ResponseBody> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().mergePullRequest(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, prIndex, mergePR);
Call<ResponseBody> call = RetrofitClient.getApiInterface(ctx).mergePullRequest(Authorization.get(ctx), repoOwner, repoName, prIndex, mergePR);
call.enqueue(new Callback<ResponseBody>() {
@ -257,45 +188,42 @@ public class MergePullRequestActivity extends BaseActivity {
if(deleteBranch) {
if(tinyDb.getString("prIsFork").equals("true")) {
if(tinyDB.getString("prIsFork").equals("true")) {
String repoFullName = tinyDb.getString("prForkFullName");
String repoFullName = tinyDB.getString("prForkFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
deleteBranchFunction(repoOwner, repoName);
Toasty.info(ctx, getString(R.string.mergePRSuccessMsg));
tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
tinyDB.putBoolean("prMerged", true);
tinyDB.putBoolean("resumePullRequests", true);
finish();
}
else {
String repoFullName = tinyDb.getString("repoFullName");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
deleteBranchFunction(repoOwner, repoName);
Toasty.info(ctx, getString(R.string.mergePRSuccessMsg));
tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
tinyDB.putBoolean("prMerged", true);
tinyDB.putBoolean("resumePullRequests", true);
finish();
}
}
else {
Toasty.info(ctx, getString(R.string.mergePRSuccessMsg));
tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
tinyDB.putBoolean("prMerged", true);
tinyDB.putBoolean("resumePullRequests", true);
finish();
}
}
@ -303,19 +231,21 @@ public class MergePullRequestActivity extends BaseActivity {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.mergePR404ErrorMsg));
Toasty.warning(ctx, getString(R.string.mergePR404ErrorMsg));
}
else if(response.code() == 405) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.mergeNotAllowed));;
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
Toasty.error(ctx, getString(R.string.genericError));
}
}
@ -333,17 +263,11 @@ public class MergePullRequestActivity extends BaseActivity {
private void deleteBranchFunction(String repoOwner, String repoName) {
TinyDB tinyDb = new TinyDB(appCtx);
String instanceUrl = tinyDb.getString("instanceUrl");
String loginUid = tinyDb.getString("loginUid");
String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String branchName = tinyDb.getString("prHeadBranch");
String branchName = tinyDB.getString("prHeadBranch");
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.deleteBranch(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName);
.getApiInterface(ctx)
.deleteBranch(Authorization.get(ctx), repoOwner, repoName, branchName);
call.enqueue(new Callback<JsonElement>() {
@ -353,9 +277,7 @@ public class MergePullRequestActivity extends BaseActivity {
if(response.code() == 204) {
Log.i("deleteBranch", "Branch deleted successfully");
}
}
@Override
@ -363,7 +285,6 @@ public class MergePullRequestActivity extends BaseActivity {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
@ -373,15 +294,11 @@ public class MergePullRequestActivity extends BaseActivity {
private void disableProcessButton() {
viewBinding.mergeButton.setEnabled(false);
viewBinding.mergeButton.setBackground(getResources().getDrawable(R.drawable.shape_buttons_disabled));
}
private void enableProcessButton() {
viewBinding.mergeButton.setEnabled(true);
viewBinding.mergeButton.setBackground(getResources().getDrawable(R.drawable.shape_buttons));
}
}

View File

@ -5,7 +5,13 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.PathsHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.net.URI;
import java.net.URISyntaxException;
import io.mikael.urlbuilder.UrlBuilder;
/**
* Author M M Arif
@ -18,21 +24,32 @@ public class OpenRepoInBrowserActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
super.onCreate(savedInstanceState);
TinyDB tinyDb = new TinyDB(appCtx);
String instanceUrlWithProtocol = "https://" + tinyDb.getString("instanceUrlRaw");
if (!tinyDb.getString("instanceUrlWithProtocol").isEmpty()) {
instanceUrlWithProtocol = tinyDb.getString("instanceUrlWithProtocol");
}
appCtx = getApplicationContext();
TinyDB tinyDb = TinyDB.getInstance(appCtx);
String repoFullNameBrowser = getIntent().getStringExtra("repoFullNameBrowser");
Uri url = Uri.parse(instanceUrlWithProtocol + "/" + repoFullNameBrowser);
Intent i = new Intent(Intent.ACTION_VIEW, url);
startActivity(i);
finish();
try {
URI instanceUrl = new URI(UrlBuilder.fromString(tinyDb.getString("instanceUrl"))
.withPath("/")
.toString());
String browserPath = PathsHelper.join(instanceUrl.getPath(), getIntent().getStringExtra("repoFullNameBrowser"));
String browserUrl = UrlBuilder.fromUri(instanceUrl)
.withPath(browserPath)
.toString();
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(browserUrl));
startActivity(i);
finish();
}
catch(URISyntaxException e) {
Toasty.error(appCtx, getString(R.string.genericError));
}
}
}

View File

@ -1,12 +1,7 @@
package org.mian.gitnex.activities;
import com.google.android.material.tabs.TabLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
@ -17,14 +12,22 @@ 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.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import org.mian.gitnex.R;
import org.mian.gitnex.fragments.MembersByOrgFragment;
import org.mian.gitnex.fragments.BottomSheetOrganizationFragment;
import org.mian.gitnex.fragments.MembersByOrgFragment;
import org.mian.gitnex.fragments.OrganizationInfoFragment;
import org.mian.gitnex.fragments.RepositoriesByOrgFragment;
import org.mian.gitnex.fragments.TeamsByOrgFragment;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.Objects;
import io.mikael.urlbuilder.UrlBuilder;
/**
* Author M M Arif
@ -32,9 +35,6 @@ import java.util.Objects;
public class OrganizationDetailActivity extends BaseActivity implements BottomSheetOrganizationFragment.BottomSheetListener {
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_org_detail;
@ -44,10 +44,8 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
String orgName = tinyDb.getString("orgName");
String orgName = tinyDB.getString("orgName");
Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
@ -65,20 +63,20 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
Typeface myTypeface;
switch(tinyDb.getInt("customFontId", -1)) {
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
break;
}
toolbarTitle.setTypeface(myTypeface);
@ -86,12 +84,18 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = vg.getChildCount();
for (int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
int tabChildCount = vgTab.getChildCount();
for (int i = 0; i < tabChildCount; i++) {
View tabViewChild = vgTab.getChildAt(i);
if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(myTypeface);
}
}
@ -99,12 +103,12 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.repo_dotted_menu, menu);
return true;
@ -115,36 +119,48 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
int id = item.getItemId();
switch (id) {
case android.R.id.home:
finish();
return true;
case R.id.repoMenu:
BottomSheetOrganizationFragment bottomSheet = new BottomSheetOrganizationFragment();
bottomSheet.show(getSupportFragmentManager(), "orgBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
if(id == android.R.id.home) {
finish();
return true;
}
else if(id == R.id.repoMenu) {
BottomSheetOrganizationFragment bottomSheet = new BottomSheetOrganizationFragment();
bottomSheet.show(getSupportFragmentManager(), "orgBottomSheet");
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
@Override
public void onButtonClicked(String text) {
TinyDB tinyDb = new TinyDB(appCtx);
switch (text) {
case "repository":
tinyDb.putBoolean("organizationAction", true);
tinyDB.putBoolean("organizationAction", true);
startActivity(new Intent(OrganizationDetailActivity.this, CreateRepoActivity.class));
break;
case "team":
startActivity(new Intent(OrganizationDetailActivity.this, CreateTeamByOrgActivity.class));
break;
}
//Log.i("clicked", text);
case "copyOrgUrl":
String url = UrlBuilder.fromString(tinyDB.getString("instanceUrl"))
.withPath("/")
.toString();
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("orgUrl", url + tinyDB.getString("orgName"));
assert clipboard != null;
clipboard.setPrimaryClip(clip);
Toasty.info(ctx, ctx.getString(R.string.copyIssueUrlToastMsg));
break;
}
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
@ -157,28 +173,33 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
@Override
public Fragment getItem(int position) {
TinyDB tinyDb = new TinyDB(appCtx);
String orgName;
if(getIntent().getStringExtra("orgName") != null || !Objects.equals(getIntent().getStringExtra("orgName"), "")) {
orgName = getIntent().getStringExtra("orgName");
}
else {
orgName = tinyDb.getString("orgName");
orgName = tinyDB.getString("orgName");
}
Fragment fragment = null;
switch (position) {
case 0: // info
return OrganizationInfoFragment.newInstance(orgName);
case 1: // repos
return RepositoriesByOrgFragment.newInstance(orgName);
case 2: // teams
return TeamsByOrgFragment.newInstance(orgName);
case 3: // members
return MembersByOrgFragment.newInstance(orgName);
}
return fragment;
}
@Override

View File

@ -1,6 +1,5 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
@ -9,6 +8,7 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider;
@ -16,7 +16,7 @@ import org.mian.gitnex.R;
import org.mian.gitnex.adapters.TeamMembersByOrgAdapter;
import org.mian.gitnex.fragments.BottomSheetOrganizationTeamsFragment;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.viewmodels.TeamMembersByOrgViewModel;
import java.util.Objects;
@ -30,9 +30,7 @@ public class OrganizationTeamMembersActivity extends BaseActivity implements Bot
private View.OnClickListener onClickListener;
private TeamMembersByOrgAdapter adapter;
private GridView mGridView;
final Context ctx = this;
private Context appCtx;
private ProgressBar progressBar;
private String teamId;
@ -45,77 +43,76 @@ public class OrganizationTeamMembersActivity extends BaseActivity implements Bot
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
TextView toolbarTitle = findViewById(R.id.toolbar_title);
noDataMembers = findViewById(R.id.noDataMembers);
mGridView = findViewById(R.id.gridView);
progressBar = findViewById(R.id.progressBar);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(getIntent().getStringExtra("teamTitle") != null && !Objects.requireNonNull(getIntent().getStringExtra("teamTitle")).equals("")) {
toolbarTitle.setText(getIntent().getStringExtra("teamTitle"));
toolbarTitle.setText(getIntent().getStringExtra("teamTitle"));
}
else {
toolbarTitle.setText(R.string.orgTeamMembers);
toolbarTitle.setText(R.string.orgTeamMembers);
}
if(getIntent().getStringExtra("teamId") != null && !Objects.requireNonNull(getIntent().getStringExtra("teamId")).equals("")){
teamId = getIntent().getStringExtra("teamId");
teamId = getIntent().getStringExtra("teamId");
}
else {
teamId = "0";
teamId = "0";
}
assert teamId != null;
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), Integer.parseInt(teamId));
fetchDataAsync(Authorization.get(ctx), Integer.parseInt(teamId));
}
@Override
public void onResume() {
super.onResume();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
TinyDB tinyDb = TinyDB.getInstance(appCtx);
if(tinyDb.getBoolean("teamActionFlag")) {
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), Integer.parseInt(teamId));
fetchDataAsync(Authorization.get(ctx), Integer.parseInt(teamId));
tinyDb.putBoolean("teamActionFlag", false);
}
}
private void fetchDataAsync(String instanceUrl, String instanceToken, int teamId) {
private void fetchDataAsync(String instanceToken, int teamId) {
TeamMembersByOrgViewModel teamMembersModel = new ViewModelProvider(this).get(TeamMembersByOrgViewModel.class);
teamMembersModel.getMembersByOrgList(instanceUrl, instanceToken, teamId, ctx).observe(this, teamMembersListMain -> {
teamMembersModel.getMembersByOrgList(instanceToken, teamId, ctx).observe(this, teamMembersListMain -> {
adapter = new TeamMembersByOrgAdapter(ctx, teamMembersListMain);
if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter);
noDataMembers.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mGridView.setAdapter(adapter);
noDataMembers.setVisibility(View.VISIBLE);
}
progressBar.setVisibility(View.GONE);
});
}
@Override
@ -124,7 +121,6 @@ public class OrganizationTeamMembersActivity extends BaseActivity implements Bot
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
return true;
}
@Override
@ -132,31 +128,32 @@ public class OrganizationTeamMembersActivity extends BaseActivity implements Bot
int id = item.getItemId();
switch(id) {
case android.R.id.home:
finish();
return true;
case R.id.genericMenu:
BottomSheetOrganizationTeamsFragment bottomSheet = new BottomSheetOrganizationTeamsFragment();
bottomSheet.show(getSupportFragmentManager(), "orgTeamsBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
if(id == android.R.id.home) {
finish();
return true;
}
else if(id == R.id.genericMenu) {
BottomSheetOrganizationTeamsFragment bottomSheet = new BottomSheetOrganizationTeamsFragment();
bottomSheet.show(getSupportFragmentManager(), "orgTeamsBottomSheet");
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
@Override
public void onButtonClicked(String text) {
TinyDB tinyDb = new TinyDB(appCtx);
if("newMember".equals(text)) {
Intent intent = new Intent(OrganizationTeamMembersActivity.this, AddNewTeamMemberActivity.class);
intent.putExtra("teamId", teamId);
startActivity(intent);
}
}
private void initCloseListener() {

View File

@ -1,10 +1,6 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.util.Patterns;
@ -13,18 +9,21 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
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.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.AddEmail;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
@ -34,8 +33,6 @@ public class ProfileEmailActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private EditText userEmail;
final Context ctx = this;
private Context appCtx;
private Button addEmailButton;
@Override
@ -47,9 +44,8 @@ public class ProfileEmailActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -67,68 +63,53 @@ public class ProfileEmailActivity extends BaseActivity {
if(!connToInternet) {
disableProcessButton();
} else {
addEmailButton.setOnClickListener(addEmailListener);
}
}
private View.OnClickListener addEmailListener = new View.OnClickListener() {
public void onClick(View v) {
processAddNewEmail();
}
};
private final View.OnClickListener addEmailListener = v -> processAddNewEmail();
private void processAddNewEmail() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newUserEmail = userEmail.getText().toString().trim();
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newUserEmail.equals("")) {
Toasty.info(ctx, getString(R.string.emailErrorEmpty));
Toasty.error(ctx, getString(R.string.emailErrorEmpty));
return;
}
else if(!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) {
Toasty.info(ctx, getString(R.string.emailErrorInvalid));
Toasty.warning(ctx, getString(R.string.emailErrorInvalid));
return;
}
List<String> newEmailList = new ArrayList<>(Arrays.asList(newUserEmail.split(",")));
disableProcessButton();
addNewEmail(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), newEmailList);
addNewEmail(Authorization.get(ctx), newEmailList);
}
private void addNewEmail(final String instanceUrl, final String token, List<String> newUserEmail) {
private void addNewEmail(final String token, List<String> newUserEmail) {
AddEmail addEmailFunc = new AddEmail(newUserEmail);
final TinyDB tinyDb = new TinyDB(appCtx);
final TinyDB tinyDb = TinyDB.getInstance(appCtx);
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getApiInterface(appCtx)
.addNewEmail(token, addEmailFunc);
call.enqueue(new Callback<JsonElement>() {
@ -138,11 +119,10 @@ public class ProfileEmailActivity extends BaseActivity {
if(response.code() == 201) {
Toasty.info(ctx, getString(R.string.emailAddedText));
Toasty.success(ctx, getString(R.string.emailAddedText));
tinyDb.putBoolean("emailsRefresh", true);
enableProcessButton();
finish();
}
else if(response.code() == 401) {
@ -151,37 +131,32 @@ public class ProfileEmailActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else if(response.code() == 422) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.emailErrorInUse));
Toasty.warning(ctx, ctx.getString(R.string.emailErrorInUse));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.labelGeneralError));
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@ -190,32 +165,18 @@ public class ProfileEmailActivity extends BaseActivity {
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
private void disableProcessButton() {
addEmailButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
addEmailButton.setBackground(shape);
}
private void enableProcessButton() {
addEmailButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
addEmailButton.setBackground(shape);
}
}

View File

@ -1,298 +0,0 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.IssueActions;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
/**
* Author M M Arif
*/
public class ReplyToIssueActivity extends BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private SocialAutoCompleteTextView addComment;
private ArrayAdapter<Mention> defaultMentionAdapter;
private Button replyButton;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_reply_to_issue;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx);
addComment = findViewById(R.id.addComment);
addComment.setShowSoftInputOnFocus(true);
defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList();
addComment.setMentionAdapter(defaultMentionAdapter);
closeActivity = findViewById(R.id.close);
TextView toolbar_title = findViewById(R.id.toolbar_title);
addComment.requestFocus();
assert imm != null;
imm.showSoftInput(addComment, InputMethodManager.SHOW_IMPLICIT);
if(!tinyDb.getString("issueTitle").isEmpty()) {
toolbar_title.setText(tinyDb.getString("issueTitle"));
}
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
replyButton = findViewById(R.id.replyButton);
if(getIntent().getStringExtra("commentBody") != null) {
addComment.setText(getIntent().getStringExtra("commentBody"));
if(getIntent().getBooleanExtra("cursorToEnd", false)) {
addComment.setSelection(addComment.length());
}
}
if(getIntent().getStringExtra("commentAction") != null && getIntent().getStringExtra("commentAction").equals("edit")) {
final String commentId = getIntent().getStringExtra("commentId");
toolbar_title.setText(getResources().getString(R.string.editCommentTitle));
replyButton.setText(getResources().getString(R.string.editCommentButtonText));
replyButton.setOnClickListener(v -> {
disableProcessButton();
IssueActions.editIssueComment(ctx, Integer.parseInt(commentId), addComment.getText().toString());
});
return;
}
if(!connToInternet) {
disableProcessButton();
} else {
replyButton.setOnClickListener(replyToIssue);
}
}
public void loadCollaboratorsList() {
final TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
String fullName = "";
for (int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(
new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
} else {
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.getMessage());
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private View.OnClickListener replyToIssue = new View.OnClickListener() {
public void onClick(View v) {
processNewCommentReply();
}
};
private void processNewCommentReply() {
String newReplyDT = addComment.getText().toString();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx);
if(!connToInternet) {
Toasty.info(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newReplyDT.equals("")) {
Toasty.info(ctx, getString(R.string.commentEmptyError));
}
else {
disableProcessButton();
replyComment(newReplyDT);
}
}
private void replyComment(String newReplyDT) {
final TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
Issues issueComment = new Issues(newReplyDT);
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.replyCommentToIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueComment);
call.enqueue(new Callback<Issues>() {
@Override
public void onResponse(@NonNull Call<Issues> call, @NonNull retrofit2.Response<Issues> response) {
if(response.code() == 201) {
Toasty.info(ctx, getString(R.string.commentSuccess));
tinyDb.putBoolean("commentPosted", true);
tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("resumePullRequests", true);
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.commentError));
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void disableProcessButton() {
replyButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
replyButton.setBackground(shape);
}
private void enableProcessButton() {
replyButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
replyButton.setBackground(shape);
}
}

View File

@ -1,7 +1,10 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Typeface;
@ -16,6 +19,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@ -29,7 +33,6 @@ import org.mian.gitnex.fragments.BottomSheetIssuesFilterFragment;
import org.mian.gitnex.fragments.BottomSheetMilestonesFilterFragment;
import org.mian.gitnex.fragments.BottomSheetPullRequestFilterFragment;
import org.mian.gitnex.fragments.BottomSheetRepoFragment;
import org.mian.gitnex.fragments.BranchesFragment;
import org.mian.gitnex.fragments.CollaboratorsFragment;
import org.mian.gitnex.fragments.FilesFragment;
import org.mian.gitnex.fragments.IssuesFragment;
@ -39,14 +42,17 @@ import org.mian.gitnex.fragments.PullRequestsFragment;
import org.mian.gitnex.fragments.ReleasesFragment;
import org.mian.gitnex.fragments.RepoInfoFragment;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -62,60 +68,16 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
private FragmentRefreshListener fragmentRefreshListener;
private FragmentRefreshListenerPr fragmentRefreshListenerPr;
private FragmentRefreshListenerMilestone fragmentRefreshListenerMilestone;
private FragmentRefreshListenerFiles fragmentRefreshListenerFiles;
final Context ctx = this;
private Context appCtx;
private String loginUid;
private String instanceToken;
// issues interface
public FragmentRefreshListener getFragmentRefreshListener() {
private String repositoryOwner;
private String repositoryName;
return fragmentRefreshListener;
}
public void setFragmentRefreshListener(FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
public interface FragmentRefreshListener {
void onRefresh(String text);
}
// pr interface
public FragmentRefreshListenerPr getFragmentRefreshListenerPr() {
return fragmentRefreshListenerPr;
}
public void setFragmentRefreshListenerPr(FragmentRefreshListenerPr fragmentRefreshListenerPr) {
this.fragmentRefreshListenerPr = fragmentRefreshListenerPr;
}
public interface FragmentRefreshListenerPr {
void onRefresh(String text);
}
// milestones interface
public FragmentRefreshListenerMilestone getFragmentRefreshListenerMilestone() {
return fragmentRefreshListenerMilestone;
}
public void setFragmentRefreshListenerMilestone(FragmentRefreshListenerMilestone fragmentRefreshListenerMilestone) {
this.fragmentRefreshListenerMilestone = fragmentRefreshListenerMilestone;
}
public interface FragmentRefreshListenerMilestone {
void onRefresh(String text);
}
public static ViewPager mViewPager;
private int tabsCount;
@Override
protected int getLayoutResourceId() {
@ -127,86 +89,90 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
String repoName1 = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String repoOwner = parts[0];
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
tinyDb.putString("repoIssuesState", "open");
tinyDb.putString("repoPrState", "open");
tinyDb.putString("milestoneState", "open");
String appLocale = tinyDb.getString("locale");
AppUtil.setAppLocale(getResources(), appLocale);
String[] repoNameParts = tinyDB.getString("repoFullName").split("/");
repositoryOwner = repoNameParts[0];
repositoryName = repoNameParts[1];
Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
toolbarTitle.setText(repositoryName);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repoName1);
Objects.requireNonNull(getSupportActionBar()).setTitle(repositoryName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
loginUid = tinyDB.getString("loginUid");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
ViewPager mViewPager = findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = findViewById(R.id.tabs);
tinyDB.putString("repoIssuesState", "open");
tinyDB.putString("repoPrState", "open");
tinyDB.putString("milestoneState", "open");
Typeface myTypeface;
switch(tinyDb.getInt("customFontId", -1)) {
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
break;
}
toolbarTitle.setTypeface(myTypeface);
toolbarTitle.setText(repoName1);
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = vg.getChildCount();
TabLayout tabLayout = findViewById(R.id.tabs);
ViewGroup viewGroup = (ViewGroup) tabLayout.getChildAt(0);
tabsCount = viewGroup.getChildCount();
for(int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
ViewGroup vgTab = (ViewGroup) viewGroup.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);
}
}
}
// only show Collaborators if you have permission to
final View collaboratorTab = vg.getChildAt(8);
if(tinyDb.getBoolean("isRepoAdmin")) {
// Only show collaborators tab, if you have permission to
View collaboratorTab = viewGroup.getChildAt(7);
if(tinyDB.getBoolean("isRepoAdmin") || new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
collaboratorTab.setVisibility(View.VISIBLE);
}
else {
tabsCount--;
collaboratorTab.setVisibility(View.GONE);
}
mViewPager = findViewById(R.id.container);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
if(tinyDb.getBoolean("enableCounterBadges")) {
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
if(tinyDB.getBoolean("enableCounterBadges")) {
@SuppressLint("InflateParams") View tabHeader2 = LayoutInflater.from(this).inflate(R.layout.badge_issue, null);
textViewBadgeIssue = tabHeader2.findViewById(R.id.counterBadgeIssue);
@ -221,61 +187,75 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
textViewBadgePull.setVisibility(View.GONE);
textViewBadgeRelease.setVisibility(View.GONE);
getRepoInfo(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName1);
getRepoInfo(Authorization.get(ctx), repositoryOwner, repositoryName);
ColorStateList textColor = tabLayout.getTabTextColors();
// issue count
// Issue count
if(textViewBadgeIssue.getText() != "") {
TabLayout.Tab tabOpenIssues = tabLayout.getTabAt(2);
Objects.requireNonNull(tabLayout.getTabAt(2)).setCustomView(tabHeader2);
assert tabOpenIssues != null;
assert tabOpenIssues != null; // FIXME This should be cleaned up
TextView openIssueTabView = Objects.requireNonNull(tabOpenIssues.getCustomView()).findViewById(R.id.counterBadgeIssueText);
openIssueTabView.setTextColor(textColor);
}
// pull count
// Pull request count
if(textViewBadgePull.getText() != "") { // only show if API returned a number
Objects.requireNonNull(tabLayout.getTabAt(3)).setCustomView(tabHeader4);
TabLayout.Tab tabOpenPulls = tabLayout.getTabAt(3);
assert tabOpenPulls != null;
assert tabOpenPulls != null; // FIXME This should be cleaned up
TextView openPullTabView = Objects.requireNonNull(tabOpenPulls.getCustomView()).findViewById(R.id.counterBadgePullText);
openPullTabView.setTextColor(textColor);
}
// release count
if(new Version("1.11.4").less(tinyDb.getString("giteaVersion"))) {
// Release count
if(new Version("1.11.4").less(tinyDB.getString("giteaVersion"))) {
if(textViewBadgeRelease.getText() != "") { // only show if API returned a number
Objects.requireNonNull(tabLayout.getTabAt(5)).setCustomView(tabHeader6);
TabLayout.Tab tabOpenRelease = tabLayout.getTabAt(5);
assert tabOpenRelease != null;
Objects.requireNonNull(tabLayout.getTabAt(4)).setCustomView(tabHeader6);
TabLayout.Tab tabOpenRelease = tabLayout.getTabAt(4);
assert tabOpenRelease != null; // FIXME This should be cleaned up
TextView openReleaseTabView = Objects.requireNonNull(tabOpenRelease.getCustomView()).findViewById(R.id.counterBadgeReleaseText);
openReleaseTabView.setTextColor(textColor);
}
}
}
checkRepositoryStarStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName1);
checkRepositoryWatchStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName1);
Intent mainIntent = getIntent();
String goToSection = mainIntent.getStringExtra("goToSection");
String goToSectionType = mainIntent.getStringExtra("goToSectionType");
if(goToSection != null) {
mainIntent.removeExtra("goToSection");
mainIntent.removeExtra("goToSectionType");
if(goToSectionType.equals("issue")) {
RepoDetailActivity.mViewPager.setCurrentItem(2);
}
else if(goToSectionType.equals("pull")) {
RepoDetailActivity.mViewPager.setCurrentItem(3);
}
}
checkRepositoryStarStatus(Authorization.get(ctx), repositoryOwner, repositoryName);
checkRepositoryWatchStatus(Authorization.get(ctx), repositoryOwner, repositoryName);
}
@Override
public void onResume() {
super.onResume();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getBoolean("enableCounterIssueBadge")) {
getRepoInfo(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
if(tinyDB.getBoolean("enableCounterIssueBadge")) {
getRepoInfo(Authorization.get(ctx), repositoryOwner, repositoryName);
}
}
@Override
@ -284,7 +264,6 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.repo_dotted_menu, menu);
return true;
}
@Override
@ -293,27 +272,44 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
int id = item.getItemId();
switch(id) {
case android.R.id.home:
finish();
return true;
case R.id.repoMenu:
BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment();
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
return true;
case R.id.filter:
BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment();
filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet");
return true;
case R.id.filterPr:
BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment();
filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet");
return true;
case R.id.filterMilestone:
BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment();
filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet");
return true;
case R.id.switchBranches:
chooseBranch();
return true;
case R.id.branchCommits:
Intent intent = new Intent(ctx, CommitsActivity.class);
intent.putExtra("branchName", tinyDB.getString("repoBranch"));
ctx.startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@ -321,69 +317,167 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
@Override
public void onButtonClicked(String text) {
TinyDB tinyDb = new TinyDB(appCtx);
switch(text) {
case "label":
startActivity(new Intent(RepoDetailActivity.this, CreateLabelActivity.class));
break;
case "newIssue":
startActivity(new Intent(RepoDetailActivity.this, CreateIssueActivity.class));
break;
case "newMilestone":
startActivity(new Intent(RepoDetailActivity.this, CreateMilestoneActivity.class));
break;
case "addCollaborator":
startActivity(new Intent(RepoDetailActivity.this, AddCollaboratorToRepositoryActivity.class));
break;
case "chooseBranch":
chooseBranch();
break;
case "createRelease":
startActivity(new Intent(RepoDetailActivity.this, CreateReleaseActivity.class));
break;
case "openWebRepo":
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(tinyDb.getString("repoHtmlUrl")));
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(tinyDB.getString("repoHtmlUrl")));
startActivity(i);
break;
case "shareRepo":
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, tinyDb.getString("repoHtmlUrl"));
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, tinyDb.getString("repoHtmlUrl"));
startActivity(Intent.createChooser(sharingIntent, tinyDb.getString("repoHtmlUrl")));
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, tinyDB.getString("repoHtmlUrl"));
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, tinyDB.getString("repoHtmlUrl"));
startActivity(Intent.createChooser(sharingIntent, tinyDB.getString("repoHtmlUrl")));
break;
case "copyRepoUrl":
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("repoUrl", tinyDB.getString("repoHtmlUrl"));
assert clipboard != null;
clipboard.setPrimaryClip(clip);
Toasty.info(ctx, ctx.getString(R.string.copyIssueUrlToastMsg));
break;
case "newFile":
startActivity(new Intent(RepoDetailActivity.this, CreateFileActivity.class));
break;
case "openIssues":
if(getFragmentRefreshListener() != null) {
getFragmentRefreshListener().onRefresh("open");
}
break;
case "closedIssues":
if(getFragmentRefreshListener() != null) {
getFragmentRefreshListener().onRefresh("closed");
}
break;
case "openPr":
if(getFragmentRefreshListenerPr() != null) {
getFragmentRefreshListenerPr().onRefresh("open");
}
break;
case "closedPr":
if(getFragmentRefreshListenerPr() != null) {
getFragmentRefreshListenerPr().onRefresh("closed");
}
break;
case "openMilestone":
if(getFragmentRefreshListenerMilestone() != null) {
getFragmentRefreshListenerMilestone().onRefresh("open");
}
break;
case "closedMilestone":
if(getFragmentRefreshListenerMilestone() != null) {
getFragmentRefreshListenerMilestone().onRefresh("closed");
}
break;
case "repoSettings":
startActivity(new Intent(RepoDetailActivity.this, RepositorySettingsActivity.class));
break;
case "newPullRequest":
startActivity(new Intent(RepoDetailActivity.this, CreatePullRequestActivity.class));
break;
}
}
private void chooseBranch() {
Call<List<Branches>> call = RetrofitClient
.getApiInterface(ctx)
.getBranches(instanceToken, repositoryOwner, repositoryName);
call.enqueue(new Callback<List<Branches>>() {
@Override
public void onResponse(@NonNull Call<List<Branches>> call, @NonNull Response<List<Branches>> response) {
if(response.code() == 200) {
List<String> branchesList = new ArrayList<>();
int selectedBranch = 0;
assert response.body() != null;
for(int i = 0; i < response.body().size(); i++) {
Branches branches = response.body().get(i);
branchesList.add(branches.getName());
if(tinyDB.getString("repoBranch").equals(branches.getName())) {
selectedBranch = i;
}
}
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx);
pBuilder.setTitle(R.string.pageTitleChooseBranch);
pBuilder.setSingleChoiceItems(branchesList.toArray(new String[0]), selectedBranch, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
tinyDB.putString("repoBranch", branchesList.get(i));
if(getFragmentRefreshListenerFiles() != null) {
getFragmentRefreshListenerFiles().onRefresh(branchesList.get(i));
}
dialogInterface.dismiss();
}
});
pBuilder.setNeutralButton(R.string.cancelButton, null);
pBuilder.create().show();
}
}
@Override
public void onFailure(@NonNull Call<List<Branches>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
@ -398,36 +492,39 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
@Override
public Fragment getItem(int position) {
TinyDB tinyDb = new TinyDB(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
Fragment fragment = null;
switch(position) {
case 0: // information
return RepoInfoFragment.newInstance(repoOwner, repoName);
case 1: // files
return FilesFragment.newInstance(repoOwner, repoName);
case 2: // issues
case 0: // Repository details
return RepoInfoFragment.newInstance(repositoryOwner, repositoryName);
case 1: // Files
return FilesFragment.newInstance(repositoryOwner, repositoryName, tinyDB.getString("repoBranch"));
case 2: // Issues
fragment = new IssuesFragment();
break;
case 3: // pull requests
case 3: // Pull requests
fragment = new PullRequestsFragment();
break;
case 4: // branches
return BranchesFragment.newInstance(repoOwner, repoName);
case 5: // releases
return ReleasesFragment.newInstance(repoOwner, repoName);
case 6: // milestones
case 4: // Releases
return ReleasesFragment.newInstance(repositoryOwner, repositoryName);
case 5: // Milestones
fragment = new MilestonesFragment();
break;
case 7: // labels
return LabelsFragment.newInstance(repoOwner, repoName);
case 8: // collaborators
return CollaboratorsFragment.newInstance(repoOwner, repoName);
case 6: // Labels
return LabelsFragment.newInstance(repositoryOwner, repositoryName);
case 7: // Collaborators
return CollaboratorsFragment.newInstance(repositoryOwner, repositoryName);
}
assert fragment != null;
return fragment;
}
@ -435,17 +532,13 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
@Override
public int getCount() {
return 9;
return tabsCount;
}
}
private void getRepoInfo(String instanceUrl, String token, final String owner, String repo) {
TinyDB tinyDb = new TinyDB(appCtx);
Call<UserRepositories> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserRepository(token, owner, repo);
private void getRepoInfo(String token, final String owner, String repo) {
Call<UserRepositories> call = RetrofitClient.getApiInterface(ctx).getUserRepository(token, owner, repo);
call.enqueue(new Callback<UserRepositories>() {
@Override
@ -453,36 +546,36 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
UserRepositories repoInfo = response.body();
if(response.isSuccessful()) {
if(response.code() == 200) {
if(response.code() == 200) {
if(tinyDB.getBoolean("enableCounterBadges")) {
if(tinyDb.getBoolean("enableCounterBadges")) {
assert repoInfo != null;
assert repoInfo != null;
if(repoInfo.getOpen_issues_count() != null) {
textViewBadgeIssue.setVisibility(View.VISIBLE);
textViewBadgeIssue.setText(repoInfo.getOpen_issues_count());
}
if(repoInfo.getOpen_issues_count() != null) {
if(repoInfo.getOpen_pull_count() != null) {
textViewBadgePull.setVisibility(View.VISIBLE);
textViewBadgePull.setText(repoInfo.getOpen_pull_count());
}
if(repoInfo.getRelease_count() != null) {
textViewBadgeRelease.setVisibility(View.VISIBLE);
textViewBadgeRelease.setText(repoInfo.getRelease_count());
}
textViewBadgeIssue.setVisibility(View.VISIBLE);
textViewBadgeIssue.setText(repoInfo.getOpen_issues_count());
}
if(repoInfo.getOpen_pull_count() != null) {
textViewBadgePull.setVisibility(View.VISIBLE);
textViewBadgePull.setText(repoInfo.getOpen_pull_count());
}
if(repoInfo.getRelease_count() != null) {
textViewBadgeRelease.setVisibility(View.VISIBLE);
textViewBadgeRelease.setText(repoInfo.getRelease_count());
}
}
}
else {
Log.e("onFailure", String.valueOf(response.code()));
}
}
@Override
@ -495,20 +588,15 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
}
private void checkRepositoryStarStatus(String instanceUrl, String instanceToken, final String owner, String repo) {
Call<JsonElement> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkRepoStarStatus(instanceToken, owner, repo);
private void checkRepositoryStarStatus(String instanceToken, final String owner, String repo) {
Call<JsonElement> call = RetrofitClient.getApiInterface(ctx).checkRepoStarStatus(instanceToken, owner, repo);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
TinyDB tinyDb = new TinyDB(appCtx);
tinyDb.putInt("repositoryStarStatus", response.code());
tinyDB.putInt("repositoryStarStatus", response.code());
}
@Override
@ -520,29 +608,29 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
}
private void checkRepositoryWatchStatus(String instanceUrl, String instanceToken, final String owner, String repo) {
private void checkRepositoryWatchStatus(String instanceToken, final String owner, String repo) {
Call<WatchInfo> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkRepoWatchStatus(instanceToken, owner, repo);
call = RetrofitClient.getApiInterface(ctx).checkRepoWatchStatus(instanceToken, owner, repo);
call.enqueue(new Callback<WatchInfo>() {
@Override
public void onResponse(@NonNull Call<WatchInfo> call, @NonNull retrofit2.Response<WatchInfo> response) {
TinyDB tinyDb = new TinyDB(appCtx);
if(response.code() == 200) {
assert response.body() != null;
if(response.body().getSubscribed()) {
tinyDb.putBoolean("repositoryWatchStatus", true);
tinyDB.putBoolean("repositoryWatchStatus", true);
}
}
else {
tinyDb.putBoolean("repositoryWatchStatus", false);
}
tinyDB.putBoolean("repositoryWatchStatus", false);
}
}
@Override
@ -554,4 +642,32 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
}
// Issues interface
public FragmentRefreshListener getFragmentRefreshListener() { return fragmentRefreshListener; }
public void setFragmentRefreshListener(FragmentRefreshListener fragmentRefreshListener) { this.fragmentRefreshListener = fragmentRefreshListener; }
public interface FragmentRefreshListener { void onRefresh(String text); }
// Pull request interface
public FragmentRefreshListenerPr getFragmentRefreshListenerPr() { return fragmentRefreshListenerPr; }
public void setFragmentRefreshListenerPr(FragmentRefreshListenerPr fragmentRefreshListenerPr) { this.fragmentRefreshListenerPr = fragmentRefreshListenerPr; }
public interface FragmentRefreshListenerPr { void onRefresh(String text); }
// Milestones interface
public FragmentRefreshListenerMilestone getFragmentRefreshListenerMilestone() { return fragmentRefreshListenerMilestone; }
public void setFragmentRefreshListenerMilestone(FragmentRefreshListenerMilestone fragmentRefreshListenerMilestone) { this.fragmentRefreshListenerMilestone = fragmentRefreshListenerMilestone; }
public interface FragmentRefreshListenerMilestone { void onRefresh(String text); }
// Files interface
public FragmentRefreshListenerFiles getFragmentRefreshListenerFiles() { return fragmentRefreshListenerFiles; }
public void setFragmentRefreshListenerFiles(FragmentRefreshListenerFiles fragmentRefreshListenerFiles) { this.fragmentRefreshListenerFiles = fragmentRefreshListenerFiles; }
public interface FragmentRefreshListenerFiles { void onRefresh(String text); }
}

View File

@ -0,0 +1,280 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoForksAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.UserRepositories;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class RepoForksActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private TextView noData;
private ProgressBar progressBar;
private String TAG = "RepositoryForks";
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int pageSize = 1;
private RecyclerView recyclerView;
private List<UserRepositories> forksList;
private RepoForksAdapter adapter;
private ProgressBar progressLoadMore;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_forks;
}
@SuppressLint("DefaultLocale")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TinyDB tinyDb = TinyDB.getInstance(appCtx);
String repoFullNameForForks = getIntent().getStringExtra("repoFullNameForForks");
assert repoFullNameForForks != null;
String[] parts = repoFullNameForForks.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
TextView toolbar_title = findViewById(R.id.toolbar_title);
toolbar_title.setMovementMethod(new ScrollingMovementMethod());
toolbar_title.setText(String.format("%s : %s", ctx.getResources().getString(R.string.infoTabRepoForksCount), repoName));
ImageView closeActivity = findViewById(R.id.close);
noData = findViewById(R.id.noData);
progressLoadMore = findViewById(R.id.progressLoadMore);
progressBar = findViewById(R.id.progress_bar);
SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
// if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances)
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
}
recyclerView = findViewById(R.id.recyclerView);
forksList = new ArrayList<>();
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(dividerItemDecoration);
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
loadInitial(Authorization.get(ctx), repoOwner, repoName, pageSize, resultLimit);
adapter.notifyDataChanged();
}, 200));
adapter = new RepoForksAdapter(ctx, forksList);
adapter.setLoadMoreListener(() -> recyclerView.post(() -> {
if(forksList.size() == resultLimit || pageSize == resultLimit) {
int page = (forksList.size() + resultLimit) / resultLimit;
loadMore(Authorization.get(ctx), repoOwner, repoName, page, resultLimit);
}
}));
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
recyclerView.setAdapter(adapter);
loadInitial(Authorization.get(ctx), repoOwner, repoName, pageSize, resultLimit);
}
private void loadInitial(String instanceToken, String repoOwner, String repoName, int pageSize, int resultLimit) {
Call<List<UserRepositories>> call = RetrofitClient
.getApiInterface(ctx)
.getRepositoryForks(instanceToken, repoOwner, repoName, pageSize, resultLimit);
call.enqueue(new Callback<List<UserRepositories>>() {
@Override
public void onResponse(@NonNull Call<List<UserRepositories>> call, @NonNull Response<List<UserRepositories>> response) {
if(response.isSuccessful()) {
assert response.body() != null;
if(response.body().size() > 0) {
forksList.clear();
forksList.addAll(response.body());
adapter.notifyDataChanged();
noData.setVisibility(View.GONE);
}
else {
forksList.clear();
adapter.notifyDataChanged();
noData.setVisibility(View.VISIBLE);
}
progressBar.setVisibility(View.GONE);
}
else {
Log.e(TAG, String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<UserRepositories>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
private void loadMore(String instanceToken, String repoOwner, String repoName, int page, int resultLimit) {
progressLoadMore.setVisibility(View.VISIBLE);
Call<List<UserRepositories>> call = RetrofitClient
.getApiInterface(ctx)
.getRepositoryForks(instanceToken, repoOwner, repoName, page, resultLimit);
call.enqueue(new Callback<List<UserRepositories>>() {
@Override
public void onResponse(@NonNull Call<List<UserRepositories>> call, @NonNull Response<List<UserRepositories>> response) {
if(response.isSuccessful()) {
//remove loading view
forksList.remove(forksList.size() - 1);
List<UserRepositories> result = response.body();
assert result != null;
if(result.size() > 0) {
pageSize = result.size();
forksList.addAll(result);
}
else {
adapter.setMoreDataAvailable(false);
}
adapter.notifyDataChanged();
progressLoadMore.setVisibility(View.GONE);
}
else {
Log.e(TAG, String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<UserRepositories>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search_menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
filter(newText);
return true;
}
});
return super.onCreateOptionsMenu(menu);
}
private void filter(String text) {
List<UserRepositories> arr = new ArrayList<>();
for(UserRepositories d : forksList) {
if(d.getName().toLowerCase().contains(text) || d.getDescription().toLowerCase().contains(text)) {
arr.add(d);
}
}
adapter.updateList(arr);
}
private void initCloseListener() {
onClickListener = view -> {
getIntent().removeExtra("repoFullNameForForks");
finish();
};
}
}

View File

@ -1,22 +1,16 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.lifecycle.ViewModelProvider;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoStargazersAdapter;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.RepoStargazersViewModel;
import java.util.List;
/**
* Author M M Arif
@ -30,9 +24,6 @@ public class RepoStargazersActivity extends BaseActivity {
private GridView mGridView;
private ProgressBar mProgressBar;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repo_stargazers;
@ -42,12 +33,6 @@ public class RepoStargazersActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
TextView toolbarTitle = findViewById(R.id.toolbar_title);
@ -65,40 +50,37 @@ public class RepoStargazersActivity extends BaseActivity {
toolbarTitle.setText(R.string.repoStargazersInMenu);
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
fetchDataAsync(Authorization.get(ctx), repoOwner, repoName);
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String repoOwner, String repoName) {
private void fetchDataAsync(String instanceToken, String repoOwner, String repoName) {
RepoStargazersViewModel repoStargazersModel = new ViewModelProvider(this).get(RepoStargazersViewModel.class);
repoStargazersModel.getRepoStargazers(instanceUrl, instanceToken, repoOwner, repoName, ctx).observe(this, new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> stargazersListMain) {
adapter = new RepoStargazersAdapter(ctx, stargazersListMain);
if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter);
noDataStargazers.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mGridView.setAdapter(adapter);
noDataStargazers.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
repoStargazersModel.getRepoStargazers(instanceToken, repoOwner, repoName, ctx).observe(this, stargazersListMain -> {
adapter = new RepoStargazersAdapter(ctx, stargazersListMain);
if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter);
noDataStargazers.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mGridView.setAdapter(adapter);
noDataStargazers.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
}

View File

@ -1,22 +1,16 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.lifecycle.ViewModelProvider;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoWatchersAdapter;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.RepoWatchersViewModel;
import java.util.List;
/**
* Author M M Arif
@ -30,9 +24,6 @@ public class RepoWatchersActivity extends BaseActivity {
private GridView mGridView;
private ProgressBar mProgressBar;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repo_watchers;
@ -42,12 +33,6 @@ public class RepoWatchersActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
TextView toolbarTitle = findViewById(R.id.toolbar_title);
@ -65,40 +50,37 @@ public class RepoWatchersActivity extends BaseActivity {
toolbarTitle.setText(R.string.repoWatchersInMenu);
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
fetchDataAsync(Authorization.get(ctx), repoOwner, repoName);
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String repoOwner, String repoName) {
private void fetchDataAsync(String instanceToken, String repoOwner, String repoName) {
RepoWatchersViewModel repoWatchersModel = new ViewModelProvider(this).get(RepoWatchersViewModel.class);
repoWatchersModel.getRepoWatchers(instanceUrl, instanceToken, repoOwner, repoName, ctx).observe(this, new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> watchersListMain) {
adapter = new RepoWatchersAdapter(ctx, watchersListMain);
if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter);
noDataWatchers.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mGridView.setAdapter(adapter);
noDataWatchers.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
repoWatchersModel.getRepoWatchers(instanceToken, repoOwner, repoName, ctx).observe(this, watchersListMain -> {
adapter = new RepoWatchersAdapter(ctx, watchersListMain);
if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter);
noDataWatchers.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mGridView.setAdapter(adapter);
noDataWatchers.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
onClickListener = view -> finish();
}
}

View File

@ -0,0 +1,416 @@
package org.mian.gitnex.activities;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.databinding.ActivityRepositorySettingsBinding;
import org.mian.gitnex.databinding.CustomRepositoryDeleteDialogBinding;
import org.mian.gitnex.databinding.CustomRepositoryEditPropertiesDialogBinding;
import org.mian.gitnex.databinding.CustomRepositoryTransferDialogBinding;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.RepositoryTransfer;
import org.mian.gitnex.models.UserRepositories;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class RepositorySettingsActivity extends BaseActivity {
private ActivityRepositorySettingsBinding viewBinding;
private CustomRepositoryEditPropertiesDialogBinding propBinding;
private CustomRepositoryDeleteDialogBinding deleteRepoBinding;
private CustomRepositoryTransferDialogBinding transferRepoBinding;
private Dialog dialogProp;
private Dialog dialogDeleteRepository;
private Dialog dialogTransferRepository;
private View.OnClickListener onClickListener;
private String loginUid;
private String instanceToken;
private String repositoryOwner;
private String repositoryName;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repository_settings;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewBinding = ActivityRepositorySettingsBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
loginUid = tinyDB.getString("loginUid");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repositoryOwner = parts[0];
repositoryName = parts[1];
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
// require gitea 1.12 or higher
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
viewBinding.transferOwnerFrame.setVisibility(View.VISIBLE);
}
viewBinding.editProperties.setOnClickListener(editProperties -> showRepositoryProperties());
viewBinding.deleteRepository.setOnClickListener(deleteRepository -> showDeleteRepository());
viewBinding.transferOwnerFrame.setOnClickListener(transferRepositoryOwnership -> showTransferRepository());
}
private void showTransferRepository() {
dialogTransferRepository = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogTransferRepository.getWindow() != null) {
dialogTransferRepository.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
transferRepoBinding = CustomRepositoryTransferDialogBinding.inflate(LayoutInflater.from(ctx));
View view = transferRepoBinding.getRoot();
dialogTransferRepository.setContentView(view);
transferRepoBinding.cancel.setOnClickListener(editProperties -> dialogTransferRepository.dismiss());
transferRepoBinding.transfer.setOnClickListener(deleteRepo -> {
String newOwner = String.valueOf(transferRepoBinding.ownerNameForTransfer.getText());
String repoName = String.valueOf(transferRepoBinding.repoNameForTransfer.getText());
if(!repositoryName.equals(repoName)) {
Toasty.error(ctx, getString(R.string.repoSettingsDeleteError));
}
else if(newOwner.matches("")) {
Toasty.error(ctx, getString(R.string.repoTransferOwnerError));
}
else {
transferRepository(newOwner);
}
});
dialogTransferRepository.show();
}
private void transferRepository(String newOwner) {
RepositoryTransfer repositoryTransfer = new RepositoryTransfer(newOwner);
Call<JsonElement> transferCall = RetrofitClient
.getApiInterface(ctx)
.transferRepository(instanceToken, repositoryOwner, repositoryName, repositoryTransfer);
transferCall.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
transferRepoBinding.transfer.setVisibility(View.GONE);
transferRepoBinding.processingRequest.setVisibility(View.VISIBLE);
if (response.code() == 202) {
dialogTransferRepository.dismiss();
Toasty.success(ctx, getString(R.string.repoTransferSuccess));
finish();
RepositoriesApi.deleteRepository((int) tinyDB.getLong("repositoryId", 0));
Intent intent = new Intent(RepositorySettingsActivity.this, MainActivity.class);
RepositorySettingsActivity.this.startActivity(intent);
}
else if (response.code() == 404) {
transferRepoBinding.transfer.setVisibility(View.VISIBLE);
transferRepoBinding.processingRequest.setVisibility(View.GONE);
Toasty.error(ctx, getString(R.string.repoTransferError));
}
else {
transferRepoBinding.transfer.setVisibility(View.VISIBLE);
transferRepoBinding.processingRequest.setVisibility(View.GONE);
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
transferRepoBinding.transfer.setVisibility(View.VISIBLE);
transferRepoBinding.processingRequest.setVisibility(View.GONE);
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
}
private void showDeleteRepository() {
dialogDeleteRepository = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogDeleteRepository.getWindow() != null) {
dialogDeleteRepository.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
deleteRepoBinding = CustomRepositoryDeleteDialogBinding.inflate(LayoutInflater.from(ctx));
View view = deleteRepoBinding.getRoot();
dialogDeleteRepository.setContentView(view);
deleteRepoBinding.cancel.setOnClickListener(editProperties -> dialogDeleteRepository.dismiss());
deleteRepoBinding.delete.setOnClickListener(deleteRepo -> {
if(!repositoryName.equals(String.valueOf(deleteRepoBinding.repoNameForDeletion.getText()))) {
Toasty.error(ctx, getString(R.string.repoSettingsDeleteError));
}
else {
deleteRepository();
}
});
dialogDeleteRepository.show();
}
private void deleteRepository() {
Call<JsonElement> deleteCall = RetrofitClient
.getApiInterface(ctx)
.deleteRepository(instanceToken, repositoryOwner, repositoryName);
deleteCall.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
deleteRepoBinding.delete.setVisibility(View.GONE);
deleteRepoBinding.processingRequest.setVisibility(View.VISIBLE);
if (response.code() == 204) {
dialogDeleteRepository.dismiss();
Toasty.success(ctx, getString(R.string.repoDeletionSuccess));
finish();
RepositoriesApi.deleteRepository((int) tinyDB.getLong("repositoryId", 0));
Intent intent = new Intent(RepositorySettingsActivity.this, MainActivity.class);
RepositorySettingsActivity.this.startActivity(intent);
}
else {
deleteRepoBinding.delete.setVisibility(View.VISIBLE);
deleteRepoBinding.processingRequest.setVisibility(View.GONE);
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
deleteRepoBinding.delete.setVisibility(View.VISIBLE);
deleteRepoBinding.processingRequest.setVisibility(View.GONE);
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
}
private void showRepositoryProperties() {
dialogProp = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogProp.getWindow() != null) {
dialogProp.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
propBinding = CustomRepositoryEditPropertiesDialogBinding.inflate(LayoutInflater.from(ctx));
View view = propBinding.getRoot();
dialogProp.setContentView(view);
propBinding.cancel.setOnClickListener(editProperties -> dialogProp.dismiss());
Call<UserRepositories> call = RetrofitClient
.getApiInterface(ctx)
.getUserRepository(instanceToken, repositoryOwner, repositoryName);
call.enqueue(new Callback<UserRepositories>() {
@Override
public void onResponse(@NonNull Call<UserRepositories> call, @NonNull retrofit2.Response<UserRepositories> response) {
UserRepositories repoInfo = response.body();
propBinding.progressBar.setVisibility(View.GONE);
propBinding.mainView.setVisibility(View.VISIBLE);
if (response.code() == 200) {
assert repoInfo != null;
propBinding.repoName.setText(repoInfo.getName());
propBinding.repoWebsite.setText(repoInfo.getWebsite());
propBinding.repoDescription.setText(repoInfo.getDescription());
propBinding.repoPrivate.setChecked(repoInfo.getPrivateFlag());
propBinding.repoAsTemplate.setChecked(repoInfo.isTemplate());
propBinding.repoEnableIssues.setChecked(repoInfo.getHas_issues());
propBinding.repoEnableIssues.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
propBinding.repoEnableTimer.setVisibility(View.VISIBLE);
}
else {
propBinding.repoEnableTimer.setVisibility(View.GONE);
}
});
if(repoInfo.getInternal_tracker() != null) {
propBinding.repoEnableTimer.setChecked(repoInfo.getInternal_tracker().isEnable_time_tracker());
}
else {
propBinding.repoEnableTimer.setVisibility(View.GONE);
}
propBinding.repoEnableWiki.setChecked(repoInfo.isHas_wiki());
propBinding.repoEnablePr.setChecked(repoInfo.isHas_pull_requests());
propBinding.repoEnableMerge.setChecked(repoInfo.isAllow_merge_commits());
propBinding.repoEnableRebase.setChecked(repoInfo.isAllow_rebase());
propBinding.repoEnableSquash.setChecked(repoInfo.isAllow_squash_merge());
propBinding.repoEnableForceMerge.setChecked(repoInfo.isAllow_rebase_explicit());
}
else {
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) {
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
propBinding.save.setOnClickListener(saveProperties -> saveRepositoryProperties(String.valueOf(propBinding.repoName.getText()),
String.valueOf(propBinding.repoWebsite.getText()),
String.valueOf(propBinding.repoDescription.getText()),
propBinding.repoPrivate.isChecked(), propBinding.repoAsTemplate.isChecked(),
propBinding.repoEnableIssues.isChecked(), propBinding.repoEnableWiki.isChecked(),
propBinding.repoEnablePr.isChecked(), propBinding.repoEnableTimer.isChecked(),
propBinding.repoEnableMerge.isChecked(), propBinding.repoEnableRebase.isChecked(),
propBinding.repoEnableSquash.isChecked(), propBinding.repoEnableForceMerge.isChecked()));
dialogProp.show();
}
private void saveRepositoryProperties(String repoName, String repoWebsite, String repoDescription,
boolean repoPrivate, boolean repoAsTemplate, boolean repoEnableIssues, boolean repoEnableWiki,
boolean repoEnablePr, boolean repoEnableTimer, boolean repoEnableMerge, boolean repoEnableRebase,
boolean repoEnableSquash, boolean repoEnableForceMerge) {
UserRepositories.internalTimeTrackerObject repoPropsTimeTracker = new UserRepositories.internalTimeTrackerObject(repoEnableTimer);
UserRepositories repoProps;
if(!repoEnableIssues) {
repoProps = new UserRepositories(repoName, repoWebsite, repoDescription, repoPrivate, repoAsTemplate, repoEnableIssues, repoEnableWiki, repoEnablePr, repoEnableMerge,
repoEnableRebase, repoEnableSquash, repoEnableForceMerge);
}
else {
repoProps = new UserRepositories(repoName, repoWebsite, repoDescription, repoPrivate, repoAsTemplate, repoEnableIssues, repoEnableWiki, repoEnablePr, repoPropsTimeTracker, repoEnableMerge,
repoEnableRebase, repoEnableSquash, repoEnableForceMerge);
}
Call<UserRepositories> propsCall = RetrofitClient
.getApiInterface(ctx)
.updateRepositoryProperties(instanceToken, repositoryOwner, repositoryName, repoProps);
propsCall.enqueue(new Callback<UserRepositories>() {
@Override
public void onResponse(@NonNull Call<UserRepositories> call, @NonNull retrofit2.Response<UserRepositories> response) {
propBinding.save.setVisibility(View.GONE);
propBinding.processingRequest.setVisibility(View.VISIBLE);
if (response.code() == 200) {
tinyDB.putBoolean("hasIssues", repoEnableIssues);
tinyDB.putBoolean("hasPullRequests", repoEnablePr);
dialogProp.dismiss();
Toasty.success(ctx, getString(R.string.repoPropertiesSaveSuccess));
if(!repositoryName.equals(repoName)) {
finish();
RepositoriesApi.updateRepositoryOwnerAndName(repositoryOwner, repoName, (int) tinyDB.getLong("repositoryId", 0));
Intent intent = new Intent(RepositorySettingsActivity.this, MainActivity.class);
RepositorySettingsActivity.this.startActivity(intent);
}
}
else {
propBinding.save.setVisibility(View.VISIBLE);
propBinding.processingRequest.setVisibility(View.GONE);
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) {
propBinding.save.setVisibility(View.VISIBLE);
propBinding.processingRequest.setVisibility(View.GONE);
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -1,16 +1,14 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import com.google.android.material.switchmaterial.SwitchMaterial;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
/**
* Author M M Arif
@ -18,22 +16,15 @@ import org.mian.gitnex.util.TinyDB;
public class SettingsAppearanceActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
private static String[] timeList = {"Pretty", "Normal"};
private static final String[] timeList = {"Pretty", "Normal"};
private static int timeSelectedChoice = 0;
private static String[] codeBlockList = {"Green - Black", "White - Black", "Grey - Black", "White - Grey", "Dark - White"};
private static int codeBlockSelectedChoice = 0;
private static String[] homeScreenList = {"My Repositories", "Starred Repositories", "Organizations", "Repositories", "Profile"};
private static int homeScreenSelectedChoice = 0;
private static String[] customFontList = {"Roboto", "Manrope", "Source Code Pro"};
private static final String[] customFontList = {"Roboto", "Manrope", "Source Code Pro"};
private static int customFontSelectedChoice = 0;
private static String[] themeList = {"Dark", "Light", "Auto (Day/Night)"};
private static final String[] themeList = {"Dark", "Light", "Auto (Light / Dark)", "Retro", "Auto (Retro / Dark)"};
private static int themeSelectedChoice = 0;
@Override
@ -46,88 +37,59 @@ public class SettingsAppearanceActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
final TinyDB tinyDb = new TinyDB(appCtx);
ImageView closeActivity = findViewById(R.id.close);
final TextView tvDateTimeSelected = findViewById(R.id.tvDateTimeSelected); // setter for time
final TextView codeBlockSelected = findViewById(R.id.codeBlockSelected); // setter for code block
final TextView homeScreenSelected = findViewById(R.id.homeScreenSelected); // setter for home screen
final TextView customFontSelected = findViewById(R.id.customFontSelected); // setter for custom font
final TextView themeSelected = findViewById(R.id.themeSelected); // setter for theme
LinearLayout timeFrame = findViewById(R.id.timeFrame);
LinearLayout codeBlockFrame = findViewById(R.id.codeBlockFrame);
LinearLayout homeScreenFrame = findViewById(R.id.homeScreenFrame);
LinearLayout customFontFrame = findViewById(R.id.customFontFrame);
LinearLayout themeFrame = findViewById(R.id.themeSelectionFrame);
Switch counterBadgesSwitch = findViewById(R.id.switchCounterBadge);
SwitchMaterial counterBadgesSwitch = findViewById(R.id.switchCounterBadge);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(!tinyDb.getString("timeStr").isEmpty()) {
tvDateTimeSelected.setText(tinyDb.getString("timeStr"));
if(!tinyDB.getString("timeStr").isEmpty()) {
tvDateTimeSelected.setText(tinyDB.getString("timeStr"));
}
if(!tinyDb.getString("codeBlockStr").isEmpty()) {
codeBlockSelected.setText(tinyDb.getString("codeBlockStr"));
if(!tinyDB.getString("customFontStr").isEmpty()) {
customFontSelected.setText(tinyDB.getString("customFontStr"));
}
if(!tinyDb.getString("homeScreenStr").isEmpty()) {
homeScreenSelected.setText(tinyDb.getString("homeScreenStr"));
}
if(!tinyDB.getString("themeStr").isEmpty()) {
if(!tinyDb.getString("customFontStr").isEmpty()) {
customFontSelected.setText(tinyDb.getString("customFontStr"));
}
if(!tinyDb.getString("themeStr").isEmpty()) {
themeSelected.setText(tinyDb.getString("themeStr"));
themeSelected.setText(tinyDB.getString("themeStr"));
}
if(timeSelectedChoice == 0) {
timeSelectedChoice = tinyDb.getInt("timeId");
}
if(codeBlockSelectedChoice == 0) {
codeBlockSelectedChoice = tinyDb.getInt("codeBlockId");
}
if(homeScreenSelectedChoice == 0) {
homeScreenSelectedChoice = tinyDb.getInt("homeScreenId");
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");
}
if(tinyDb.getBoolean("enableCounterBadges")) {
counterBadgesSwitch.setChecked(true);
}
else {
counterBadgesSwitch.setChecked(false);
}
counterBadgesSwitch.setChecked(tinyDB.getBoolean("enableCounterBadges"));
// counter badge switcher
counterBadgesSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
tinyDb.putBoolean("enableCounterBadges", true);
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
}
else {
tinyDb.putBoolean("enableCounterBadges", false);
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
}
tinyDB.putBoolean("enableCounterBadges", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
// theme selection dialog
@ -136,31 +98,24 @@ public class SettingsAppearanceActivity extends BaseActivity {
AlertDialog.Builder tsBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
tsBuilder.setTitle(getResources().getString(R.string.themeSelectorDialogTitle));
if(themeSelectedChoice != -1) {
tsBuilder.setCancelable(true);
}
else {
tsBuilder.setCancelable(false);
}
tsBuilder.setCancelable(themeSelectedChoice != -1);
tsBuilder.setSingleChoiceItems(themeList, themeSelectedChoice, (dialogInterfaceTheme, i) -> {
themeSelectedChoice = i;
themeSelected.setText(themeList[i]);
tinyDb.putString("themeStr", themeList[i]);
tinyDb.putInt("themeId", i);
tinyDB.putString("themeStr", themeList[i]);
tinyDB.putInt("themeId", i);
tinyDb.putBoolean("refreshParent", true);
tinyDB.putBoolean("refreshParent", true);
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceTheme.dismiss();
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = tsBuilder.create();
cfDialog.show();
});
// custom font dialog
@ -169,114 +124,24 @@ public class SettingsAppearanceActivity extends BaseActivity {
AlertDialog.Builder cfBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
cfBuilder.setTitle(R.string.settingsCustomFontSelectorDialogTitle);
if(customFontSelectedChoice != -1) {
cfBuilder.setCancelable(true);
}
else {
cfBuilder.setCancelable(false);
}
cfBuilder.setCancelable(customFontSelectedChoice != -1);
cfBuilder.setSingleChoiceItems(customFontList, customFontSelectedChoice, (dialogInterfaceCustomFont, i) -> {
customFontSelectedChoice = i;
customFontSelected.setText(customFontList[i]);
tinyDb.putString("customFontStr", customFontList[i]);
tinyDb.putInt("customFontId", i);
tinyDB.putString("customFontStr", customFontList[i]);
tinyDB.putInt("customFontId", i);
tinyDb.putBoolean("refreshParent", true);
tinyDB.putBoolean("refreshParent", true);
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceCustomFont.dismiss();
Toasty.info(appCtx, appCtx.getResources().getString(R.string.settingsSave));
Toasty.success(appCtx, appCtx.getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = cfBuilder.create();
cfDialog.show();
});
// home screen dialog
homeScreenFrame.setOnClickListener(view -> {
AlertDialog.Builder hsBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
hsBuilder.setTitle(R.string.settingshomeScreenSelectorDialogTitle);
if(homeScreenSelectedChoice != -1) {
hsBuilder.setCancelable(true);
}
else {
hsBuilder.setCancelable(false);
}
hsBuilder.setSingleChoiceItems(homeScreenList, homeScreenSelectedChoice, (dialogInterfaceHomeScreen, i) -> {
homeScreenSelectedChoice = i;
homeScreenSelected.setText(homeScreenList[i]);
tinyDb.putString("homeScreenStr", homeScreenList[i]);
tinyDb.putInt("homeScreenId", i);
dialogInterfaceHomeScreen.dismiss();
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog hsDialog = hsBuilder.create();
hsDialog.show();
});
// code block dialog
codeBlockFrame.setOnClickListener(view -> {
AlertDialog.Builder cBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
cBuilder.setTitle(R.string.settingsCodeBlockSelectorDialogTitle);
if(codeBlockSelectedChoice != -1) {
cBuilder.setCancelable(true);
}
else {
cBuilder.setCancelable(false);
}
cBuilder.setSingleChoiceItems(codeBlockList, codeBlockSelectedChoice, (dialogInterfaceCodeBlock, i) -> {
codeBlockSelectedChoice = i;
codeBlockSelected.setText(codeBlockList[i]);
tinyDb.putString("codeBlockStr", codeBlockList[i]);
tinyDb.putInt("codeBlockId", i);
switch(codeBlockList[i]) {
case "White - Black":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.white));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
break;
case "Grey - Black":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorAccent));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
break;
case "White - Grey":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.white));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.colorAccent));
break;
case "Dark - White":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorPrimary));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.white));
break;
default:
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorLightGreen));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
break;
}
dialogInterfaceCodeBlock.dismiss();
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cDialog = cBuilder.create();
cDialog.show();
});
// time and date dialog
@ -285,44 +150,36 @@ public class SettingsAppearanceActivity extends BaseActivity {
AlertDialog.Builder tBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
tBuilder.setTitle(R.string.settingsTimeSelectorDialogTitle);
if(timeSelectedChoice != -1) {
tBuilder.setCancelable(true);
}
else {
tBuilder.setCancelable(false);
}
tBuilder.setCancelable(timeSelectedChoice != -1);
tBuilder.setSingleChoiceItems(timeList, timeSelectedChoice, (dialogInterfaceTime, i) -> {
timeSelectedChoice = i;
tvDateTimeSelected.setText(timeList[i]);
tinyDb.putString("timeStr", timeList[i]);
tinyDb.putInt("timeId", i);
tinyDB.putString("timeStr", timeList[i]);
tinyDB.putInt("timeId", i);
if("Normal".equals(timeList[i])) {
tinyDb.putString("dateFormat", "normal");
tinyDB.putString("dateFormat", "normal");
}
else {
tinyDb.putString("dateFormat", "pretty");
tinyDB.putString("dateFormat", "pretty");
}
dialogInterfaceTime.dismiss();
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog tDialog = tBuilder.create();
tDialog.show();
});
}
private void initCloseListener() {
onClickListener = view -> {
finish();
};
onClickListener = view -> finish();
}
}

View File

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

View File

@ -1,16 +1,14 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import com.google.android.material.switchmaterial.SwitchMaterial;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
/**
* Author M M Arif
@ -18,10 +16,9 @@ import org.mian.gitnex.util.TinyDB;
public class SettingsFileViewerActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
private static String[] fileViewerSourceCodeThemesList = {"Sublime", "Arduino Light", "Github", "Far ", "Ir Black", "Android Studio"};
private static final String[] fileViewerSourceCodeThemesList = {"Sublime", "Arduino Light", "Github", "Far ", "Ir Black", "Android Studio"};
private static int fileViewerSourceCodeThemesSelectedChoice = 0;
@Override
@ -34,9 +31,6 @@ public class SettingsFileViewerActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
final TinyDB tinyDb = new TinyDB(appCtx);
ImageView closeActivity = findViewById(R.id.close);
@ -47,22 +41,17 @@ public class SettingsFileViewerActivity extends BaseActivity {
LinearLayout sourceCodeThemeFrame = findViewById(R.id.sourceCodeThemeFrame);
Switch pdfModeSwitch = findViewById(R.id.switchPdfMode);
SwitchMaterial pdfModeSwitch = findViewById(R.id.switchPdfMode);
if(!tinyDb.getString("fileviewerSourceCodeThemeStr").isEmpty()) {
fileViewerSourceCodeThemesSelected.setText(tinyDb.getString("fileviewerSourceCodeThemeStr"));
if(!tinyDB.getString("fileviewerSourceCodeThemeStr").isEmpty()) {
fileViewerSourceCodeThemesSelected.setText(tinyDB.getString("fileviewerSourceCodeThemeStr"));
}
if(fileViewerSourceCodeThemesSelectedChoice == 0) {
fileViewerSourceCodeThemesSelectedChoice = tinyDb.getInt("fileviewerThemeId");
fileViewerSourceCodeThemesSelectedChoice = tinyDB.getInt("fileviewerThemeId");
}
if(tinyDb.getBoolean("enablePdfMode")) {
pdfModeSwitch.setChecked(true);
}
else {
pdfModeSwitch.setChecked(false);
}
pdfModeSwitch.setChecked(tinyDB.getBoolean("enablePdfMode"));
// fileviewer srouce code theme selection dialog
sourceCodeThemeFrame.setOnClickListener(view -> {
@ -70,46 +59,31 @@ public class SettingsFileViewerActivity extends BaseActivity {
AlertDialog.Builder fvtsBuilder = new AlertDialog.Builder(SettingsFileViewerActivity.this);
fvtsBuilder.setTitle(R.string.fileviewerSourceCodeThemeSelectorDialogTitle);
if(fileViewerSourceCodeThemesSelectedChoice != -1) {
fvtsBuilder.setCancelable(true);
}
else {
fvtsBuilder.setCancelable(false);
}
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);
tinyDB.putString("fileviewerSourceCodeThemeStr", fileViewerSourceCodeThemesList[i]);
tinyDB.putInt("fileviewerSourceCodeThemeId", i);
dialogInterfaceTheme.dismiss();
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = fvtsBuilder.create();
cfDialog.show();
});
// pdf night mode switcher
pdfModeSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(isChecked) {
tinyDb.putBoolean("enablePdfMode", true);
tinyDb.putString("enablePdfModeInit", "yes");
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
}
else {
tinyDb.putBoolean("enablePdfMode", false);
tinyDb.putString("enablePdfModeInit", "yes");
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
}
tinyDB.putBoolean("enablePdfMode", isChecked);
tinyDB.putString("enablePdfModeInit", "yes");
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
}
private void initCloseListener() {

View File

@ -0,0 +1,176 @@
package org.mian.gitnex.activities;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsGeneralBinding;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Author M M Arif
*/
public class SettingsGeneralActivity extends BaseActivity {
private ActivitySettingsGeneralBinding viewBinding;
private View.OnClickListener onClickListener;
private List<String> homeScreenList;
private static int homeScreenSelectedChoice = 0;
private List<String> defaultScreen;
private static int defaultLinkHandlerScreenSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_general;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewBinding = ActivitySettingsGeneralBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
initCloseListener();
viewBinding.close.setOnClickListener(onClickListener);
// home screen
String[] homeDefaultScreen_ = {getResources().getString(R.string.pageTitleMyRepos), getResources().getString(R.string.pageTitleStarredRepos), getResources().getString(R.string.pageTitleOrganizations),
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),
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")) {
homeDefaultScreen_ = homeDefaultScreenNew;
}
homeScreenList = new ArrayList<>(Arrays.asList(homeDefaultScreen_));
String[] homeScreenArray = new String[homeScreenList.size()];
homeScreenList.toArray(homeScreenArray);
if(homeScreenSelectedChoice == 0) {
homeScreenSelectedChoice = tinyDB.getInt("homeScreenId");
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleMyRepos));
}
if(homeScreenSelectedChoice == 1) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleStarredRepos));
}
else if(homeScreenSelectedChoice == 2) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleOrganizations));
}
else if(homeScreenSelectedChoice == 3) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleRepositories));
}
else if(homeScreenSelectedChoice == 4) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleProfile));
}
else if(homeScreenSelectedChoice == 5) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleExplore));
}
else if(homeScreenSelectedChoice == 6) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.titleDrafts));
}
else if(homeScreenSelectedChoice == 7) {
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleNotifications));
}
viewBinding.homeScreenFrame.setOnClickListener(setDefaultHomeScreen -> {
AlertDialog.Builder hsBuilder = new AlertDialog.Builder(SettingsGeneralActivity.this);
hsBuilder.setTitle(R.string.settingsHomeScreenSelectorDialogTitle);
hsBuilder.setCancelable(homeScreenSelectedChoice != -1);
hsBuilder.setSingleChoiceItems(homeScreenArray, homeScreenSelectedChoice, (dialogInterfaceHomeScreen, i) -> {
homeScreenSelectedChoice = i;
viewBinding.homeScreenSelected.setText(homeScreenArray[i]);
tinyDB.putInt("homeScreenId", i);
dialogInterfaceHomeScreen.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog hsDialog = hsBuilder.create();
hsDialog.show();
});
// home screen
// link handler
String[] defaultScreen_ = {getResources().getString(R.string.generalDeepLinkSelectedText), getResources().getString(R.string.navRepos), getResources().getString(R.string.navOrgs), getResources().getString(R.string.pageTitleNotifications), getResources().getString(R.string.navExplore)};
defaultScreen = new ArrayList<>(Arrays.asList(defaultScreen_));
String[] linksArray = new String[defaultScreen.size()];
defaultScreen.toArray(linksArray);
if(defaultLinkHandlerScreenSelectedChoice == 0) {
defaultLinkHandlerScreenSelectedChoice = tinyDB.getInt("defaultScreenId");
viewBinding.generalDeepLinkSelected.setText(getResources().getString(R.string.generalDeepLinkSelectedText));
}
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 -> {
AlertDialog.Builder dlBuilder = new AlertDialog.Builder(SettingsGeneralActivity.this);
dlBuilder.setTitle(R.string.linkSelectorDialogTitle);
dlBuilder.setCancelable(defaultLinkHandlerScreenSelectedChoice != -1);
dlBuilder.setSingleChoiceItems(linksArray, defaultLinkHandlerScreenSelectedChoice, (dialogInterfaceHomeScreen, i) -> {
defaultLinkHandlerScreenSelectedChoice = i;
viewBinding.generalDeepLinkSelected.setText(linksArray[i]);
tinyDB.putInt("defaultScreenId", i);
dialogInterfaceHomeScreen.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog dlDialog = dlBuilder.create();
dlDialog.show();
});
// link handler
}
private void initCloseListener() { onClickListener = view -> finish(); }
}

View File

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

View File

@ -1,13 +1,11 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Switch;
import com.google.android.material.switchmaterial.SwitchMaterial;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
/**
* Author M M Arif
@ -15,7 +13,6 @@ import org.mian.gitnex.util.TinyDB;
public class SettingsReportsActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
@Override
@ -28,44 +25,26 @@ public class SettingsReportsActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
ImageView closeActivity = findViewById(R.id.close);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
Switch crashReportsSwitch = findViewById(R.id.crashReportsSwitch);
SwitchMaterial crashReportsSwitch = findViewById(R.id.crashReportsSwitch);
if(tinyDb.getBoolean("crashReportingEnabled")) {
crashReportsSwitch.setChecked(true);
}
else {
crashReportsSwitch.setChecked(false);
}
crashReportsSwitch.setChecked(tinyDB.getBoolean("crashReportingEnabled"));
// crash reports switcher
crashReportsSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(isChecked) {
tinyDb.putBoolean("crashReportingEnabled", true);
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
}
else {
tinyDb.putBoolean("crashReportingEnabled", false);
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
}
tinyDB.putBoolean("crashReportingEnabled", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
}
private void initCloseListener() {
onClickListener = view -> {
finish();
};
onClickListener = view -> finish();
}
}

View File

@ -11,14 +11,10 @@ import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import org.apache.commons.io.FileUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.FilesData;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.ssl.MemorizingTrustManager;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
/**
* Author M M Arif
@ -26,13 +22,12 @@ import java.util.HashSet;
public class SettingsSecurityActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
private static String[] cacheSizeDataList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"};
private static final String[] cacheSizeDataList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"};
private static int cacheSizeDataSelectedChoice = 0;
private static String[] cacheSizeImagesList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"};
private static final String[] cacheSizeImagesList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"};
private static int cacheSizeImagesSelectedChoice = 0;
@Override
@ -45,9 +40,6 @@ public class SettingsSecurityActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
ImageView closeActivity = findViewById(R.id.close);
@ -63,28 +55,29 @@ public class SettingsSecurityActivity extends BaseActivity {
LinearLayout cacheSizeImagesFrame = findViewById(R.id.cacheSizeImagesSelectionFrame);
LinearLayout clearCacheFrame = findViewById(R.id.clearCacheSelectionFrame);
if(!tinyDb.getString("cacheSizeStr").isEmpty()) {
cacheSizeDataSelected.setText(tinyDb.getString("cacheSizeStr"));
if(!tinyDB.getString("cacheSizeStr").isEmpty()) {
cacheSizeDataSelected.setText(tinyDB.getString("cacheSizeStr"));
}
if(!tinyDb.getString("cacheSizeImagesStr").isEmpty()) {
cacheSizeImagesSelected.setText(tinyDb.getString("cacheSizeImagesStr"));
if(!tinyDB.getString("cacheSizeImagesStr").isEmpty()) {
cacheSizeImagesSelected.setText(tinyDB.getString("cacheSizeImagesStr"));
}
if(cacheSizeDataSelectedChoice == 0) {
cacheSizeDataSelectedChoice = tinyDb.getInt("cacheSizeId");
cacheSizeDataSelectedChoice = tinyDB.getInt("cacheSizeId");
}
if(cacheSizeImagesSelectedChoice == 0) {
cacheSizeImagesSelectedChoice = tinyDb.getInt("cacheSizeImagesId");
cacheSizeImagesSelectedChoice = tinyDB.getInt("cacheSizeImagesId");
}
// clear cache setter
File cacheDir = appCtx.getCacheDir();
long size__ = FilesData.getFileSizeRecursively(new HashSet<>(), cacheDir);
if(size__ > 0) {
clearCacheSelected.setText(String.valueOf(AppUtil.formatFileSizeInDetail(size__)));
}
clearCacheSelected.setText(FileUtils.byteCountToDisplaySize((int) FileUtils.sizeOfDirectory(cacheDir)));
// clear cache
clearCacheFrame.setOnClickListener(v1 -> {
@ -101,14 +94,11 @@ public class SettingsSecurityActivity extends BaseActivity {
FileUtils.mkdir(cacheDir.getAbsolutePath());
this.recreate();
this.overridePendingTransition(0, 0);
}
catch (IOException e) {
Log.e("SettingsSecurity", e.toString());
}
});
builder.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss());
@ -122,28 +112,21 @@ public class SettingsSecurityActivity extends BaseActivity {
AlertDialog.Builder tsBuilder = new AlertDialog.Builder(SettingsSecurityActivity.this);
tsBuilder.setTitle(getResources().getString(R.string.cacheSizeImagesDialogHeader));
if(cacheSizeImagesSelectedChoice != -1) {
tsBuilder.setCancelable(true);
}
else {
tsBuilder.setCancelable(false);
}
tsBuilder.setCancelable(cacheSizeImagesSelectedChoice != -1);
tsBuilder.setSingleChoiceItems(cacheSizeImagesList, cacheSizeImagesSelectedChoice, (dialogInterfaceTheme, i) -> {
cacheSizeImagesSelectedChoice = i;
cacheSizeImagesSelected.setText(cacheSizeImagesList[i]);
tinyDb.putString("cacheSizeImagesStr", cacheSizeImagesList[i]);
tinyDb.putInt("cacheSizeImagesId", i);
tinyDB.putString("cacheSizeImagesStr", cacheSizeImagesList[i]);
tinyDB.putInt("cacheSizeImagesId", i);
dialogInterfaceTheme.dismiss();
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = tsBuilder.create();
cfDialog.show();
});
// cache size data selection dialog
@ -152,28 +135,21 @@ public class SettingsSecurityActivity extends BaseActivity {
AlertDialog.Builder tsBuilder = new AlertDialog.Builder(SettingsSecurityActivity.this);
tsBuilder.setTitle(getResources().getString(R.string.cacheSizeDataDialogHeader));
if(cacheSizeDataSelectedChoice != -1) {
tsBuilder.setCancelable(true);
}
else {
tsBuilder.setCancelable(false);
}
tsBuilder.setCancelable(cacheSizeDataSelectedChoice != -1);
tsBuilder.setSingleChoiceItems(cacheSizeDataList, cacheSizeDataSelectedChoice, (dialogInterfaceTheme, i) -> {
cacheSizeDataSelectedChoice = i;
cacheSizeDataSelected.setText(cacheSizeDataList[i]);
tinyDb.putString("cacheSizeStr", cacheSizeDataList[i]);
tinyDb.putInt("cacheSizeId", i);
tinyDB.putString("cacheSizeStr", cacheSizeDataList[i]);
tinyDB.putInt("cacheSizeId", i);
dialogInterfaceTheme.dismiss();
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = tsBuilder.create();
cfDialog.show();
});
// certs deletion
@ -187,28 +163,22 @@ public class SettingsSecurityActivity extends BaseActivity {
appCtx.getSharedPreferences(MemorizingTrustManager.KEYSTORE_NAME, Context.MODE_PRIVATE).edit().remove(MemorizingTrustManager.KEYSTORE_KEY).apply();
tinyDb.putBoolean("loggedInMode", false);
tinyDb.remove("basicAuthPassword");
tinyDb.putBoolean("basicAuthFlag", false);
//tinyDb.clear();
tinyDB.putBoolean("loggedInMode", false);
tinyDB.remove("basicAuthPassword");
tinyDB.putBoolean("basicAuthFlag", false);
Intent loginActivityIntent = new Intent().setClass(appCtx, LoginActivity.class);
loginActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
appCtx.startActivity(loginActivityIntent);
});
builder.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss());
builder.create().show();
});
}
private void initCloseListener() {
onClickListener = view -> {
finish();
};
}
onClickListener = view -> finish();
}
}

View File

@ -1,6 +1,5 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@ -11,7 +10,6 @@ import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
/**
* Author M M Arif
@ -19,11 +17,10 @@ import org.mian.gitnex.util.TinyDB;
public class SettingsTranslationActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
private static String[] langList = {"English", "Arabic", "Chinese", "Finnish", "French", "German", "Italian", "Latvian", "Persian", "Polish", "Portuguese/Brazilian", "Russian", "Serbian", "Spanish", "Turkish",
"Ukrainian"};
private static String[] langList = {"English", "Arabic", "Chinese", "Czech", "Finnish", "French", "German", "Italian", "Latvian", "Persian",
"Polish", "Portuguese/Brazilian", "Russian", "Serbian", "Spanish", "Turkish", "Ukrainian"};
private static int langSelectedChoice = 0;
@Override
@ -36,9 +33,6 @@ public class SettingsTranslationActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
ImageView closeActivity = findViewById(R.id.close);
@ -60,12 +54,14 @@ public class SettingsTranslationActivity extends BaseActivity {
});
if(!tinyDb.getString("localeStr").isEmpty()) {
tvLanguageSelected.setText(tinyDb.getString("localeStr"));
if(!tinyDB.getString("localeStr").isEmpty()) {
tvLanguageSelected.setText(tinyDB.getString("localeStr"));
}
if(langSelectedChoice == 0) {
langSelectedChoice = tinyDb.getInt("langId");
langSelectedChoice = tinyDB.getInt("langId");
}
// language dialog
@ -74,92 +70,103 @@ public class SettingsTranslationActivity extends BaseActivity {
AlertDialog.Builder lBuilder = new AlertDialog.Builder(SettingsTranslationActivity.this);
lBuilder.setTitle(R.string.settingsLanguageSelectorDialogTitle);
if(langSelectedChoice != -1) {
lBuilder.setCancelable(true);
}
else {
lBuilder.setCancelable(false);
}
lBuilder.setCancelable(langSelectedChoice != -1);
lBuilder.setSingleChoiceItems(langList, langSelectedChoice, (dialogInterface, i) -> {
langSelectedChoice = i;
tvLanguageSelected.setText(langList[i]);
tinyDb.putString("localeStr", langList[i]);
tinyDb.putInt("langId", i);
tinyDB.putString("localeStr", langList[i]);
tinyDB.putInt("langId", i);
switch(langList[i]) {
case "Arabic":
tinyDb.putString("locale", "ar");
tinyDB.putString("locale", "ar");
break;
case "Chinese":
tinyDb.putString("locale", "zh");
tinyDB.putString("locale", "zh");
break;
case "Czech":
tinyDB.putString("locale", "cs");
break;
case "Finnish":
tinyDb.putString("locale", "fi");
tinyDB.putString("locale", "fi");
break;
case "French":
tinyDb.putString("locale", "fr");
tinyDB.putString("locale", "fr");
break;
case "German":
tinyDb.putString("locale", "de");
tinyDB.putString("locale", "de");
break;
case "Italian":
tinyDb.putString("locale", "it");
tinyDB.putString("locale", "it");
break;
case "Latvian":
tinyDb.putString("locale", "lv");
tinyDB.putString("locale", "lv");
break;
case "Persian":
tinyDb.putString("locale", "fa");
tinyDB.putString("locale", "fa");
break;
case "Polish":
tinyDb.putString("locale", "pl");
tinyDB.putString("locale", "pl");
break;
case "Portuguese/Brazilian":
tinyDb.putString("locale", "pt");
tinyDB.putString("locale", "pt");
break;
case "Russian":
tinyDb.putString("locale", "ru");
tinyDB.putString("locale", "ru");
break;
case "Serbian":
tinyDb.putString("locale", "sr");
tinyDB.putString("locale", "sr");
break;
case "Spanish":
tinyDb.putString("locale", "es");
tinyDB.putString("locale", "es");
break;
case "Turkish":
tinyDb.putString("locale", "tr");
tinyDB.putString("locale", "tr");
break;
case "Ukrainian":
tinyDb.putString("locale", "uk");
tinyDB.putString("locale", "uk");
break;
default:
tinyDb.putString("locale", "en");
tinyDB.putString("locale", "en");
break;
}
tinyDb.putBoolean("refreshParent", true);
tinyDB.putBoolean("refreshParent", true);
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterface.dismiss();
Toasty.info(appCtx, getResources().getString(R.string.settingsSave));
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
lBuilder.setNegativeButton(getString(R.string.cancelButton), (dialog, which) -> dialog.dismiss());
lBuilder.setNeutralButton(getString(R.string.cancelButton), null);
AlertDialog lDialog = lBuilder.create();
lDialog.show();
});
}
private void initCloseListener() {
onClickListener = view -> {
finish();
};
onClickListener = view -> finish();
}
}

View File

@ -1,70 +0,0 @@
package org.mian.gitnex.activities;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.SponsorsAdapter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Author M M Arif
*/
public class SponsorsActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_sponsors;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
ImageView closeActivity = findViewById(R.id.close);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
Resources res = getResources();
CharSequence[] sponsorsInfo = res.getTextArray(R.array.sponsorsInfo);
List<CharSequence> sponsorsList = new ArrayList<>(Arrays.asList(sponsorsInfo));
RecyclerView mRecyclerView = findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(appCtx));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
SponsorsAdapter adapter = new SponsorsAdapter(sponsorsList);
mRecyclerView.setAdapter(adapter);
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}

View File

@ -86,7 +86,7 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
holder.userRole.setVisibility(View.VISIBLE);
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.textColor(mCtx.getResources().getColor(R.color.white))
.textColor(mCtx.getResources().getColor(R.color.colorWhite))
.fontSize(44)
.width(180)
.height(60)

View File

@ -0,0 +1,136 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.Collaborators;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
/**
* Author M M Arif
*/
public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdapter.AssigneesViewHolder> {
private Context mCtx;
private List<Collaborators> assigneesList;
private List<String> assigneesStrings = new ArrayList<>();
private List<String> currentAssignees;
private AssigneesListAdapterListener assigneesListener;
public interface AssigneesListAdapterListener {
void assigneesInterface(List<String> data);
}
public AssigneesListAdapter(Context mCtx, List<Collaborators> dataMain, AssigneesListAdapterListener assigneesListener, List<String> currentAssignees) {
this.mCtx = mCtx;
this.assigneesList = dataMain;
this.assigneesListener = assigneesListener;
this.currentAssignees = currentAssignees;
}
static class AssigneesViewHolder extends RecyclerView.ViewHolder {
private CheckBox assigneesSelection;
private TextView assigneesName;
private ImageView assigneesAvatar;
private AssigneesViewHolder(View itemView) {
super(itemView);
this.setIsRecyclable(false);
assigneesSelection = itemView.findViewById(R.id.assigneesSelection);
assigneesName = itemView.findViewById(R.id.assigneesName);
assigneesAvatar = itemView.findViewById(R.id.assigneesAvatar);
}
}
@NonNull
@Override
public AssigneesListAdapter.AssigneesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_assignees_list, parent, false);
return new AssigneesListAdapter.AssigneesViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull AssigneesListAdapter.AssigneesViewHolder holder, int position) {
Collaborators currentItem = assigneesList.get(position);
if(currentItem.getFull_name().equals("")) {
holder.assigneesName.setText(currentItem.getLogin());
}
else {
holder.assigneesName.setText(currentItem.getFull_name());
}
PicassoService
.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(holder.assigneesAvatar);
for(int i = 0; i < assigneesList.size(); i++) {
if(assigneesStrings.contains(currentItem.getLogin())) {
holder.assigneesSelection.setChecked(true);
}
}
currentAssignees = new ArrayList<>(new LinkedHashSet<>(currentAssignees));
for(int i = 0; i < currentAssignees.size(); i++) {
if(currentAssignees.contains(currentItem.getLogin())) {
holder.assigneesSelection.setChecked(true);
assigneesStrings.add(currentAssignees.get(i));
}
}
assigneesListener.assigneesInterface(assigneesStrings);
holder.assigneesSelection.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(isChecked) {
assigneesStrings.add(currentItem.getLogin());
}
else {
assigneesStrings.remove(currentItem.getLogin());
}
assigneesListener.assigneesInterface(assigneesStrings);
});
assigneesStrings = new ArrayList<>(new LinkedHashSet<>(assigneesStrings));
}
@Override
public int getItemCount() {
return assigneesList.size();
}
public void updateList(List<String> list) {
currentAssignees = list;
notifyDataSetChanged();
}
}

View File

@ -1,90 +0,0 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.CommitsActivity;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
/**
* Author M M Arif
*/
public class BranchesAdapter extends RecyclerView.Adapter<BranchesAdapter.BranchesViewHolder> {
private List<Branches> branchesList;
private Context mCtx;
static class BranchesViewHolder extends RecyclerView.ViewHolder {
private TextView branchNameTv;
private TextView branchCommitAuthor;
private BranchesViewHolder(View itemView) {
super(itemView);
branchNameTv = itemView.findViewById(R.id.branchName);
branchCommitAuthor = itemView.findViewById(R.id.branchCommitAuthor);
Button branchCommitHash = itemView.findViewById(R.id.branchCommitHash);
branchCommitHash.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), CommitsActivity.class);
intent.putExtra("branchName", String.valueOf(branchNameTv.getText()));
Objects.requireNonNull(v.getContext()).startActivity(intent);
}
});
}
}
public BranchesAdapter(Context mCtx, List<Branches> branchesMain) {
this.mCtx = mCtx;
this.branchesList = branchesMain;
}
@NonNull
@Override
public BranchesAdapter.BranchesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_branches, parent, false);
return new BranchesAdapter.BranchesViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull BranchesAdapter.BranchesViewHolder holder, int position) {
final TinyDB tinyDb = new TinyDB(mCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
Branches currentItem = branchesList.get(position);
holder.branchNameTv.setText(currentItem.getName());
if(currentItem.getCommit().getAuthor().getName() != null || !currentItem.getCommit().getAuthor().getName().equals("")) {
holder.branchCommitAuthor.setText(mCtx.getResources().getString(R.string.commitAuthor, currentItem.getCommit().getAuthor().getName()));
}
else {
holder.branchCommitAuthor.setText(mCtx.getResources().getString(R.string.commitAuthor, currentItem.getCommit().getAuthor().getUsername()));
}
}
@Override
public int getItemCount() {
return branchesList.size();
}
}

View File

@ -14,8 +14,8 @@ import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Commits;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import java.util.Locale;
@ -112,7 +112,7 @@ public class CommitsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
@SuppressLint("SetTextI18n")
void bindData(Commits commitsModel) {
final TinyDB tinyDb = new TinyDB(ctx);
final TinyDB tinyDb = TinyDB.getInstance(ctx);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");

View File

@ -0,0 +1,148 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.database.models.DraftWithRepository;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.List;
/**
* Author M M Arif
*/
public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsViewHolder> {
private List<DraftWithRepository> draftsList;
private final FragmentManager fragmentManager;
private final Context mCtx;
class DraftsViewHolder extends RecyclerView.ViewHolder {
private DraftWithRepository draftWithRepository;
private final TextView draftText;
private final TextView repoInfo;
private final ImageView editCommentStatus;
private DraftsViewHolder(View itemView) {
super(itemView);
draftText = itemView.findViewById(R.id.draftText);
repoInfo = itemView.findViewById(R.id.repoInfo);
ImageView deleteDraft = itemView.findViewById(R.id.deleteDraft);
editCommentStatus = itemView.findViewById(R.id.editCommentStatus);
deleteDraft.setOnClickListener(itemDelete -> {
int getDraftId = draftWithRepository.getDraftId();
deleteDraft(getAdapterPosition());
DraftsApi draftsApi = new DraftsApi(mCtx);
draftsApi.deleteSingleDraft(getDraftId);
});
itemView.setOnClickListener(itemEdit -> {
Bundle bundle = new Bundle();
bundle.putString("commentBody", draftWithRepository.getDraftText());
bundle.putString("issueNumber", String.valueOf(draftWithRepository.getIssueId()));
bundle.putString("repositoryId", String.valueOf(draftWithRepository.getRepositoryId()));
bundle.putString("draftTitle", repoInfo.getText().toString());
bundle.putString("commentId", draftWithRepository.getCommentId());
bundle.putString("draftId", String.valueOf(draftWithRepository.getDraftId()));
if(!draftWithRepository.getCommentId().isEmpty()) {
bundle.putString("commentAction", "edit");
}
TinyDB tinyDb = TinyDB.getInstance(mCtx);
tinyDb.putString("issueNumber", String.valueOf(draftWithRepository.getIssueId()));
tinyDb.putLong("repositoryId", draftWithRepository.getRepositoryId());
tinyDb.putString("issueType", draftWithRepository.getIssueType());
tinyDb.putString("repoFullName", draftWithRepository.getRepositoryOwner() + "/" + draftWithRepository.getRepositoryName());
BottomSheetReplyFragment bottomSheetReplyFragment = BottomSheetReplyFragment.newInstance(bundle);
bottomSheetReplyFragment.setOnInteractedListener(() -> mCtx.startActivity(new Intent(mCtx, IssueDetailActivity.class)));
bottomSheetReplyFragment.show(fragmentManager, "replyBottomSheet");
});
}
}
public DraftsAdapter(Context mCtx, FragmentManager fragmentManager, List<DraftWithRepository> draftsListMain) {
this.mCtx = mCtx;
this.fragmentManager = fragmentManager;
this.draftsList = draftsListMain;
}
private void deleteDraft(int position) {
draftsList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, draftsList.size());
Toasty.success(mCtx, mCtx.getResources().getString(R.string.draftsSingleDeleteSuccess));
}
@NonNull
@Override
public DraftsAdapter.DraftsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_drafts, parent, false);
return new DraftsViewHolder(v);
}
@SuppressLint("DefaultLocale")
@Override
public void onBindViewHolder(@NonNull DraftsAdapter.DraftsViewHolder holder, int 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>";
Spanned headTitle = Html.fromHtml(issueNumber + " " + currentItem.getRepositoryOwner() + " / " + currentItem.getRepositoryName());
holder.repoInfo.setText(headTitle);
holder.draftWithRepository = currentItem;
new Markdown(mCtx, currentItem.getDraftText(), holder.draftText);
if(!currentItem.getCommentId().equalsIgnoreCase("new")) {
holder.editCommentStatus.setVisibility(View.VISIBLE);
}
else {
holder.editCommentStatus.setVisibility(View.GONE);
}
}
@Override
public int getItemCount() {
return draftsList.size();
}
public void updateList(List<DraftWithRepository> list) {
draftsList = list;
notifyDataSetChanged();
}
}

View File

@ -1,6 +1,8 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
@ -9,6 +11,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
@ -18,16 +21,20 @@ import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.RepoForksActivity;
import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
@ -37,7 +44,6 @@ import retrofit2.Callback;
public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepositoriesAdapter.ReposSearchViewHolder> {
private List<UserRepositories> searchedReposList;
private Context mCtx;
@ -58,6 +64,10 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
private TextView repoStars;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private LinearLayout archiveRepo;
private TextView repoBranch;
private TextView htmlUrl;
private ReposSearchViewHolder(View itemView) {
@ -73,6 +83,10 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
repoForks = itemView.findViewById(R.id.repoForks);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
repoBranch = itemView.findViewById(R.id.repoBranch);
htmlUrl = itemView.findViewById(R.id.htmlUrl);
itemView.setOnClickListener(v -> {
@ -82,24 +96,45 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", repoFullName.getText().toString());
TinyDB tinyDb = new TinyDB(context);
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
tinyDb.putString("repoBranch", repoBranch.getText().toString());
String[] parts = fullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
String[] parts = repoFullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchInfo watch = new WatchInfo();
Call<WatchInfo> call;
call = RetrofitClient.getInstance(instanceUrl, context).getApiInterface().checkRepoWatchStatus(token, repoOwner, repoName);
call = RetrofitClient.getApiInterface(context).checkRepoWatchStatus(token, repoOwner, repoName);
call.enqueue(new Callback<WatchInfo>() {
@ -117,7 +152,7 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
if(response.code() != 404) {
Toasty.info(context, context.getString(R.string.genericApiStatusError));
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
@ -129,10 +164,11 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) {
tinyDb.putBoolean("repoWatch", false);
Toasty.info(context, context.getString(R.string.genericApiStatusError));
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
});
}
context.startActivity(intent);
@ -148,13 +184,26 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
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(fullName.getText());
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);
@ -182,6 +231,15 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
});
repoForksList.setOnClickListener(forks -> {
Intent intentW = new Intent(context, RepoForksActivity.class);
intentW.putExtra("repoFullNameForForks", fullName.getText());
context.startActivity(intentW);
dialog.dismiss();
});
});
}
@ -199,10 +257,10 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
@Override
public void onBindViewHolder(@NonNull final ExploreRepositoriesAdapter.ReposSearchViewHolder holder, int position) {
final UserRepositories currentItem = searchedReposList.get(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;
int color = generator.getColor(currentItem.getName());
@ -227,12 +285,14 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullname());
holder.fullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold);
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_public);
holder.repoPrivatePublic.setVisibility(View.GONE);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count());
@ -242,6 +302,13 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
}
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
}
@Override
@ -250,4 +317,9 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
return searchedReposList.size();
}
public void notifyDataChanged() {
notifyDataSetChanged();
}
}

View File

@ -10,10 +10,10 @@ import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.apache.commons.io.FileUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Files;
import org.mian.gitnex.util.AppUtil;
import java.util.ArrayList;
import java.util.List;
@ -37,6 +37,8 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
class FilesViewHolder extends RecyclerView.ViewHolder {
private ImageView fileTypeImage;
private ImageView dirTypeImage;
private ImageView unknownTypeImage;
private TextView fileName;
private TextView fileType;
private TextView fileInfo;
@ -46,28 +48,27 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
super(itemView);
fileName = itemView.findViewById(R.id.fileName);
fileTypeImage = itemView.findViewById(R.id.fileImage);
dirTypeImage = itemView.findViewById(R.id.dirImage);
unknownTypeImage = itemView.findViewById(R.id.unknownImage);
fileType = itemView.findViewById(R.id.fileType);
fileInfo = itemView.findViewById(R.id.fileInfo);
//ImageView filesDropdownMenu = itemView.findViewById(R.id.filesDropdownMenu);
fileName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
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.info(context, context.getString(R.string.filesGenericError));
}
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));
}
});
@ -160,15 +161,22 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
holder.fileName.setText(currentItem.getName());
if(currentItem.getType().equals("file")) {
holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_file_new));
holder.fileTypeImage.setVisibility(View.VISIBLE);
holder.dirTypeImage.setVisibility(View.GONE);
holder.unknownTypeImage.setVisibility(View.GONE);
holder.fileInfo.setVisibility(View.VISIBLE);
holder.fileInfo.setText(AppUtil.formatFileSizeInDetail(currentItem.getSize()));
holder.fileInfo.setText(FileUtils.byteCountToDisplaySize(currentItem.getSize()));
}
else if(currentItem.getType().equals("dir")) {
holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_folder_24));
holder.dirTypeImage.setVisibility(View.VISIBLE);
holder.unknownTypeImage.setVisibility(View.GONE);
holder.fileTypeImage.setVisibility(View.GONE);
holder.fileInfo.setVisibility(View.GONE);
}
else {
holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_question_mark_24));
holder.unknownTypeImage.setVisibility(View.VISIBLE);
holder.dirTypeImage.setVisibility(View.GONE);
holder.fileTypeImage.setVisibility(View.GONE);
}
}

View File

@ -2,8 +2,8 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
@ -12,10 +12,12 @@ import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.fragment.app.FragmentManager;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.helpers.DiffTextView;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.models.FileDiffView;
import org.mian.gitnex.views.DiffTextView;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
@ -35,21 +37,23 @@ public class FilesDiffAdapter extends BaseAdapter {
private static int COLOR_SELECTED;
private static int COLOR_FONT;
private Context context;
private List<FileDiffView> fileDiffViews;
private final Context context;
private final FragmentManager fragmentManager;
private final List<FileDiffView> fileDiffViews;
public FilesDiffAdapter(Context context, List<FileDiffView> fileDiffViews) {
public FilesDiffAdapter(Context context, FragmentManager fragmentManager, List<FileDiffView> fileDiffViews) {
this.context = context;
this.fragmentManager = fragmentManager;
this.fileDiffViews = fileDiffViews;
selectedViews = new ConcurrentSkipListMap<>();
COLOR_ADDED = getColorFromAttribute(R.attr.diffAddedColor);
COLOR_REMOVED = getColorFromAttribute(R.attr.diffRemovedColor);
COLOR_NORMAL = getColorFromAttribute(R.attr.primaryBackgroundColor);
COLOR_SELECTED = getColorFromAttribute(R.attr.diffSelectedColor);
COLOR_FONT = getColorFromAttribute(R.attr.inputTextColor);
COLOR_ADDED = AppUtil.getColorFromAttribute(context, R.attr.diffAddedColor);
COLOR_REMOVED = AppUtil.getColorFromAttribute(context, R.attr.diffRemovedColor);
COLOR_NORMAL = AppUtil.getColorFromAttribute(context, R.attr.primaryBackgroundColor);
COLOR_SELECTED = AppUtil.getColorFromAttribute(context, R.attr.diffSelectedColor);
COLOR_FONT = AppUtil.getColorFromAttribute(context, R.attr.inputTextColor);
}
@ -86,7 +90,7 @@ public class FilesDiffAdapter extends BaseAdapter {
FileDiffView data = (FileDiffView) getItem(position);
headerFileName.setText(data.getFileName());
if(data.isFileType()) {
if(data.isFileBinary()) {
diffStats.setVisibility(View.GONE);
diffLines.addView(getMessageView(context.getResources().getString(R.string.binaryFileError)));
@ -97,7 +101,7 @@ public class FilesDiffAdapter extends BaseAdapter {
diffStats.setVisibility(View.VISIBLE);
headerFileInfo.setText(data.getFileInfo());
String[] codeLines = getLines(data.getFileContents());
String[] codeLines = getLines(data.toString());
if(MAXIMUM_LINES > codeLines.length) {
@ -182,7 +186,6 @@ public class FilesDiffAdapter extends BaseAdapter {
});
diffTextView.setOnLongClickListener(v -> {
if(((DiffTextView) v).getCurrentBackgroundColor() == COLOR_SELECTED) {
@ -201,12 +204,11 @@ public class FilesDiffAdapter extends BaseAdapter {
selectedViews.clear();
Intent intent = new Intent(context, ReplyToIssueActivity.class);
intent.putExtra("commentBody", stringBuilder.toString());
intent.putExtra("cursorToEnd", true);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Bundle bundle = new Bundle();
bundle.putString("commentBody", stringBuilder.toString());
bundle.putBoolean("cursorToEnd", true);
context.startActivity(intent);
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
}
@ -255,13 +257,4 @@ public class FilesDiffAdapter extends BaseAdapter {
}
private int getColorFromAttribute(int resid) {
TypedValue typedValue = new TypedValue();
context.getTheme().resolveAttribute(resid, typedValue, true);
return typedValue.data;
}
}

View File

@ -1,53 +1,41 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Spanned;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.gson.JsonElement;
import com.vdurmont.emoji.EmojiParser;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UserMentions;
import org.mian.gitnex.models.IssueComments;
import org.mian.gitnex.util.TinyDB;
import java.util.Collection;
import java.util.Collections;
import org.mian.gitnex.views.ReactionList;
import org.mian.gitnex.views.ReactionSpinner;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin;
import io.noties.markwon.core.MarkwonTheme;
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tasklist.TaskListPlugin;
import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.DefaultMediaDecoder;
import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin;
import io.noties.markwon.image.SchemeHandler;
import io.noties.markwon.image.gif.GifMediaDecoder;
import io.noties.markwon.image.svg.SvgMediaDecoder;
import io.noties.markwon.linkify.LinkifyPlugin;
import retrofit2.Call;
import retrofit2.Callback;
@ -57,84 +45,115 @@ import retrofit2.Callback;
public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdapter.IssueCommentViewHolder> {
private List<IssueComments> issuesComments;
private Context mCtx;
private final Context ctx;
private final TinyDB tinyDB;
private final Bundle bundle;
private final List<IssueComments> issuesComments;
private final FragmentManager fragmentManager;
private final BottomSheetReplyFragment.OnInteractedListener onInteractedListener;
public IssueCommentsAdapter(Context mCtx, List<IssueComments> issuesCommentsMain) {
public IssueCommentsAdapter(Context ctx, Bundle bundle, List<IssueComments> issuesCommentsMain, FragmentManager fragmentManager, BottomSheetReplyFragment.OnInteractedListener onInteractedListener) {
this.mCtx = mCtx;
this.ctx = ctx;
this.bundle = bundle;
this.issuesComments = issuesCommentsMain;
this.fragmentManager = fragmentManager;
this.onInteractedListener = onInteractedListener;
tinyDB = TinyDB.getInstance(ctx);
}
class IssueCommentViewHolder extends RecyclerView.ViewHolder {
private TextView issueNumber;
private TextView commendId;
private ImageView issueCommenterAvatar;
private TextView issueComment;
private TextView issueCommentDate;
private TextView commendBodyRaw;
private TextView commentModified;
private TextView commenterUsername;
private TextView htmlUrl;
private IssueComments issueComment;
private IssueCommentViewHolder(View itemView) {
private final ImageView avatar;
private final TextView author;
private final TextView information;
private final TextView comment;
private final LinearLayout commentReactionBadges;
super(itemView);
private IssueCommentViewHolder(View view) {
issueNumber = itemView.findViewById(R.id.issueNumber);
commendId = itemView.findViewById(R.id.commendId);
issueCommenterAvatar = itemView.findViewById(R.id.issueCommenterAvatar);
issueComment = itemView.findViewById(R.id.issueComment);
issueCommentDate = itemView.findViewById(R.id.issueCommentDate);
ImageView commentsOptionsMenu = itemView.findViewById(R.id.commentsOptionsMenu);
commendBodyRaw = itemView.findViewById(R.id.commendBodyRaw);
commentModified = itemView.findViewById(R.id.commentModified);
commenterUsername = itemView.findViewById(R.id.commenterUsername);
htmlUrl = itemView.findViewById(R.id.htmlUrl);
super(view);
commentsOptionsMenu.setOnClickListener(v -> {
avatar = view.findViewById(R.id.avatar);
author = view.findViewById(R.id.author);
information = view.findViewById(R.id.information);
ImageView menu = view.findViewById(R.id.menu);
comment = view.findViewById(R.id.comment);
commentReactionBadges = view.findViewById(R.id.commentReactionBadges);
menu.setOnClickListener(v -> {
final Context ctx = v.getContext();
final TinyDB tinyDb = new TinyDB(ctx);
final String loginUid = tinyDb.getString("loginUid");
final String loginUid = tinyDB.getString("loginUid");
@SuppressLint("InflateParams") View view = LayoutInflater.from(ctx).inflate(R.layout.bottom_sheet_issue_comments, null);
@SuppressLint("InflateParams") View vw = LayoutInflater.from(ctx).inflate(R.layout.bottom_sheet_issue_comments, null);
TextView commentMenuEdit = view.findViewById(R.id.commentMenuEdit);
TextView commentShare = view.findViewById(R.id.issueCommentShare);
TextView commentMenuDelete = view.findViewById(R.id.commentMenuDelete);
TextView commentMenuEdit = vw.findViewById(R.id.commentMenuEdit);
TextView commentShare = vw.findViewById(R.id.issueCommentShare);
TextView commentMenuQuote = vw.findViewById(R.id.commentMenuQuote);
TextView commentMenuCopy = vw.findViewById(R.id.commentMenuCopy);
TextView commentMenuDelete = vw.findViewById(R.id.commentMenuDelete);
TextView issueCommentCopyUrl = vw.findViewById(R.id.issueCommentCopyUrl);
if(!loginUid.contentEquals(commenterUsername.getText())) {
if(!loginUid.contentEquals(issueComment.getUser().getUsername())) {
commentMenuEdit.setVisibility(View.GONE);
commentMenuDelete.setVisibility(View.GONE);
}
if(issueComment.getBody().isEmpty()) {
commentMenuCopy.setVisibility(View.GONE);
}
BottomSheetDialog dialog = new BottomSheetDialog(ctx);
dialog.setContentView(view);
dialog.setContentView(vw);
dialog.show();
commentMenuEdit.setOnClickListener(ediComment -> {
LinearLayout linearLayout = vw.findViewById(R.id.commentReactionButtons);
Intent intent = new Intent(ctx, ReplyToIssueActivity.class);
intent.putExtra("commentId", commendId.getText());
intent.putExtra("commentAction", "edit");
intent.putExtra("commentBody", commendBodyRaw.getText());
ctx.startActivity(intent);
Bundle bundle1 = new Bundle();
bundle1.putAll(bundle);
bundle1.putInt("commentId", issueComment.getId());
ReactionSpinner reactionSpinner = new ReactionSpinner(ctx, bundle1);
reactionSpinner.setOnInteractedListener(() -> {
tinyDB.putBoolean("commentEdited", true);
onInteractedListener.onInteracted();
dialog.dismiss();
});
commentShare.setOnClickListener(ediComment -> {
linearLayout.addView(reactionSpinner);
commentMenuEdit.setOnClickListener(v1 -> {
Bundle bundle = new Bundle();
bundle.putInt("commentId", issueComment.getId());
bundle.putString("commentAction", "edit");
bundle.putString("commentBody", issueComment.getBody());
BottomSheetReplyFragment bottomSheetReplyFragment = BottomSheetReplyFragment.newInstance(bundle);
bottomSheetReplyFragment.setOnInteractedListener(onInteractedListener);
bottomSheetReplyFragment.show(fragmentManager, "replyBottomSheet");
dialog.dismiss();
});
commentShare.setOnClickListener(v1 -> {
// get comment Url
CharSequence commentUrl = htmlUrl.getText();
CharSequence commentUrl = issueComment.getHtml_url();
// share issue comment
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
String intentHeader = tinyDb.getString("issueNumber") + ctx.getResources().getString(R.string.hash) + "issuecomment-" + commendId.getText() + " " + tinyDb.getString("issueTitle");
String intentHeader = tinyDB.getString("issueNumber") + ctx.getResources().getString(R.string.hash) + "issuecomment-" + issueComment.getId() + " " + tinyDB.getString("issueTitle");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, intentHeader);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, commentUrl);
ctx.startActivity(Intent.createChooser(sharingIntent, intentHeader));
@ -143,9 +162,66 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
});
commentMenuDelete.setOnClickListener(deleteComment -> {
issueCommentCopyUrl.setOnClickListener(v1 -> {
deleteIssueComment(ctx, Integer.parseInt(commendId.getText().toString()), getAdapterPosition());
// comment Url
CharSequence commentUrl = issueComment.getHtml_url();
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
assert clipboard != null;
ClipData clip = ClipData.newPlainText(commentUrl, commentUrl);
clipboard.setPrimaryClip(clip);
dialog.dismiss();
Toasty.success(ctx, ctx.getString(R.string.copyIssueUrlToastMsg));
});
commentMenuQuote.setOnClickListener(v1 -> {
StringBuilder stringBuilder = new StringBuilder();
String commenterName = issueComment.getUser().getUsername();
if(!commenterName.equals(tinyDB.getString("userLogin"))) {
stringBuilder.append("@").append(commenterName).append("\n\n");
}
String[] lines = issueComment.getBody().split("\\R");
for(String line : lines) {
stringBuilder.append(">").append(line).append("\n");
}
stringBuilder.append("\n");
Bundle bundle = new Bundle();
bundle.putString("commentBody", stringBuilder.toString());
bundle.putBoolean("cursorToEnd", true);
dialog.dismiss();
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
});
commentMenuCopy.setOnClickListener(v1 -> {
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
assert clipboard != null;
ClipData clip = ClipData.newPlainText("Comment on issue #" + tinyDB.getString("issueNumber"), issueComment.getBody());
clipboard.setPrimaryClip(clip);
dialog.dismiss();
Toasty.success(ctx, ctx.getString(R.string.copyIssueCommentToastMsg));
});
commentMenuDelete.setOnClickListener(v1 -> {
deleteIssueComment(ctx, issueComment.getId(), getAdapterPosition());
dialog.dismiss();
});
@ -166,22 +242,19 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
private void deleteIssueComment(final Context ctx, final int commentId, int position) {
final TinyDB tinyDb = new TinyDB(ctx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String[] repoFullName = tinyDb.getString("repoFullName").split("/");
final String loginUid = tinyDB.getString("loginUid");
final String instanceToken = "token " + tinyDB.getString(loginUid + "-token");
String[] repoFullName = tinyDB.getString("repoFullName").split("/");
if (repoFullName.length != 2) {
return;
}
final String repoOwner = repoFullName[0];
final String repoName = repoFullName[1];
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
Call<JsonElement> call = RetrofitClient
.getApiInterface(ctx)
.deleteComment(instanceToken, repoOwner, repoName, commentId);
call.enqueue(new Callback<JsonElement>() {
@ -189,47 +262,40 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 204) {
switch(response.code()) {
updateAdapter(position);
Toasty.info(ctx, ctx.getResources().getString(R.string.deleteCommentSuccess));
case 204:
updateAdapter(position);
Toasty.success(ctx, ctx.getResources().getString(R.string.deleteCommentSuccess));
break;
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle),
case 401:
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle),
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
break;
case 404:
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
break;
default:
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
else if(response.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
}
@NonNull
@ -240,109 +306,63 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
return new IssueCommentsAdapter.IssueCommentViewHolder(v);
}
@SuppressLint("SetTextI18n")
@Override
public void onBindViewHolder(@NonNull IssueCommentsAdapter.IssueCommentViewHolder holder, int position) {
final TinyDB tinyDb = new TinyDB(mCtx);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
String timeFormat = tinyDB.getString("dateFormat");
IssueComments issueComment = issuesComments.get(position);
IssueComments currentItem = issuesComments.get(position);
holder.issueComment = issueComment;
holder.author.setText(issueComment.getUser().getUsername());
holder.htmlUrl.setText(currentItem.getHtml_url());
holder.commenterUsername.setText(currentItem.getUser().getUsername());
holder.commendId.setText(String.valueOf(currentItem.getId()));
holder.commendBodyRaw.setText(currentItem.getBody());
PicassoService.getInstance(ctx).get()
.load(issueComment.getUser().getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(4, 0))
.resize(AppUtil.getPixelsFromDensity(ctx, 35), AppUtil.getPixelsFromDensity(ctx, 35))
.centerCrop()
.into(holder.avatar);
if(!currentItem.getUser().getFull_name().equals("")) {
holder.issueCommenterAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCommenter) + currentItem.getUser().getFull_name(), mCtx));
}
else {
holder.issueCommenterAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCommenter) + currentItem.getUser().getLogin(), mCtx));
}
new Markdown(ctx, EmojiParser.parseToUnicode(issueComment.getBody()), holder.comment);
PicassoService.getInstance(mCtx).get().load(currentItem.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.issueCommenterAvatar);
StringBuilder informationBuilder = null;
if(issueComment.getCreated_at() != null) {
String cleanIssueComments = currentItem.getBody().trim();
final Markwon markwon = Markwon.builder(Objects.requireNonNull(mCtx)).usePlugin(CorePlugin.create()).usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
@Override
public void configureImages(@NonNull ImagesPlugin plugin) {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = mCtx.getResources().getIdentifier(raw.substring("drawable://".length()), "drawable", mCtx.getPackageName());
final Drawable drawable = mCtx.getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(drawable -> null);
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
if(timeFormat.equals("pretty")) {
informationBuilder = new StringBuilder(TimeHelper.formatTime(issueComment.getCreated_at(), Locale.getDefault(), "pretty", ctx));
holder.information
.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(issueComment.getCreated_at()), ctx));
}
})).usePlugin(new AbstractMarkwonPlugin() {
else if(timeFormat.equals("normal")) {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder.codeTextColor(tinyDb.getInt("codeBlockColor")).codeBackgroundColor(tinyDb.getInt("codeBlockBackground")).linkColor(mCtx.getResources().getColor(R.color.lightBlue));
informationBuilder = new StringBuilder(TimeHelper.formatTime(issueComment.getCreated_at(), Locale.getDefault(), "normal", ctx));
}
}).usePlugin(TablePlugin.create(mCtx)).usePlugin(TaskListPlugin.create(mCtx)).usePlugin(HtmlPlugin.create()).usePlugin(StrikethroughPlugin.create()).usePlugin(LinkifyPlugin.create()).build();
if(!issueComment.getCreated_at().equals(issueComment.getUpdated_at())) {
Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueComments));
markwon.setParsedMarkdown(holder.issueComment, UserMentions.UserMentionsFunc(mCtx, bodyWithMD, cleanIssueComments));
String edited;
if(!currentItem.getUpdated_at().equals(currentItem.getCreated_at())) {
edited = mCtx.getResources().getString(R.string.colorfulBulletSpan) + mCtx.getResources().getString(R.string.modifiedText);
holder.commentModified.setVisibility(View.VISIBLE);
holder.commentModified.setText(edited);
holder.commentModified.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getUpdated_at()), mCtx));
}
else {
holder.commentModified.setVisibility(View.INVISIBLE);
if(informationBuilder != null) {
informationBuilder.append(ctx.getString(R.string.colorfulBulletSpan)).append(ctx.getString(R.string.modifiedText));
}
}
}
holder.issueCommentDate.setText(TimeHelper.formatTime(currentItem.getCreated_at(), new Locale(locale), timeFormat, mCtx));
holder.information.setText(informationBuilder);
Bundle bundle1 = new Bundle();
bundle1.putAll(bundle);
bundle1.putInt("commentId", issueComment.getId());
ReactionList reactionList = new ReactionList(ctx, bundle1);
holder.commentReactionBadges.addView(reactionList);
if(timeFormat.equals("pretty")) {
holder.issueCommentDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getCreated_at()), mCtx));
}
}
@Override
public int getItemCount() {
return issuesComments.size();
}
}

View File

@ -18,8 +18,8 @@ import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.util.TinyDB;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@ -123,9 +123,9 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText());
TinyDB tinyDb = new TinyDB(context);
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "issue");
tinyDb.putString("issueType", "Issue");
context.startActivity(intent);
});
@ -136,9 +136,9 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText());
TinyDB tinyDb = new TinyDB(context);
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "issue");
tinyDb.putString("issueType", "Issue");
context.startActivity(intent);
});
@ -148,7 +148,7 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
@SuppressLint("SetTextI18n")
void bindData(Issues issuesModel) {
final TinyDB tinyDb = new TinyDB(context);
final TinyDB tinyDb = TinyDB.getInstance(context);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");

View File

@ -3,26 +3,25 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.amulyakhare.textdrawable.TextDrawable;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.core.widget.ImageViewCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.CreateLabelActivity;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.helpers.LabelWidthCalculator;
import org.mian.gitnex.models.Labels;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
/**
* Author M M Arif
@ -39,12 +38,17 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
private TextView labelTitle;
private TextView labelId;
private TextView labelColor;
private ImageView labelsView;
private CardView labelView;
private ImageView labelIcon;
private TextView labelName;
private LabelsViewHolder(View itemView) {
super(itemView);
labelsView = itemView.findViewById(R.id.labelsView);
labelView = itemView.findViewById(R.id.labelView);
labelIcon = itemView.findViewById(R.id.labelIcon);
labelName = itemView.findViewById(R.id.labelName);
ImageView labelsOptionsMenu = itemView.findViewById(R.id.labelsOptionsMenu);
labelTitle = itemView.findViewById(R.id.labelTitle);
labelId = itemView.findViewById(R.id.labelId);
@ -119,19 +123,13 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
String labelName = currentItem.getName();
int color = Color.parseColor("#" + labelColor);
int contrastColor = new ColorInverter().getContrastColor(color);
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.useFont(Typeface.DEFAULT)
.bold()
.textColor(new ColorInverter().getContrastColor(color))
.fontSize(35)
.width(LabelWidthCalculator.calculateLabelWidth(labelName, Typeface.DEFAULT, 40, 20))
.height(55)
.endConfig()
.buildRoundRect(labelName, color, 10);
ImageViewCompat.setImageTintList(holder.labelIcon, ColorStateList.valueOf(contrastColor));
holder.labelsView.setImageDrawable(drawable);
holder.labelName.setTextColor(contrastColor);
holder.labelName.setText(labelName);
holder.labelView.setCardBackgroundColor(color);
}
@ -140,4 +138,4 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
return labelsList.size();
}
}
}

View File

@ -0,0 +1,132 @@
package org.mian.gitnex.adapters;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.models.Labels;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
/**
* Author M M Arif
*/
public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.LabelsViewHolder> {
private List<Integer> currentLabelsIds;
private List<Labels> labels;
private List<String> labelsStrings = new ArrayList<>();
private List<Integer> labelsIds = new ArrayList<>();
private LabelsListAdapterListener labelsListener;
public interface LabelsListAdapterListener {
void labelsInterface(List<String> data);
void labelsIdsInterface(List<Integer> data);
}
public LabelsListAdapter(List<Labels> labelsMain, LabelsListAdapterListener labelsListener, List<Integer> currentLabelsIds) {
this.labels = labelsMain;
this.labelsListener = labelsListener;
this.currentLabelsIds = currentLabelsIds;
}
static class LabelsViewHolder extends RecyclerView.ViewHolder {
private CheckBox labelSelection;
private TextView labelText;
private ImageView labelColor;
private LabelsViewHolder(View itemView) {
super(itemView);
this.setIsRecyclable(false);
labelSelection = itemView.findViewById(R.id.labelSelection);
labelText = itemView.findViewById(R.id.labelText);
labelColor = itemView.findViewById(R.id.labelColor);
}
}
@NonNull
@Override
public LabelsListAdapter.LabelsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_labels_list, parent, false);
return new LabelsListAdapter.LabelsViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull LabelsListAdapter.LabelsViewHolder holder, int position) {
Labels currentItem = labels.get(position);
String labelColor = currentItem.getColor();
int color = Color.parseColor("#" + labelColor);
holder.labelText.setText(currentItem.getName());
holder.labelColor.setBackgroundColor(color);
for(int i = 0; i < labelsIds.size(); i++) {
if(labelsStrings.contains(currentItem.getName())) {
holder.labelSelection.setChecked(true);
}
}
currentLabelsIds = new ArrayList<>(new LinkedHashSet<>(currentLabelsIds));
for(int i = 0; i < currentLabelsIds.size(); i++) {
if(currentLabelsIds.contains(currentItem.getId())) {
holder.labelSelection.setChecked(true);
labelsIds.add(currentLabelsIds.get(i));
}
}
labelsListener.labelsIdsInterface(labelsIds);
holder.labelSelection.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(isChecked) {
labelsStrings.add(currentItem.getName());
labelsIds.add(currentItem.getId());
}
else {
labelsStrings.remove(currentItem.getName());
labelsIds.remove(Integer.valueOf(currentItem.getId()));
}
labelsListener.labelsInterface(labelsStrings);
labelsListener.labelsIdsInterface(labelsIds);
});
labelsIds = new ArrayList<>(new LinkedHashSet<>(labelsIds));
}
@Override
public int getItemCount() {
return labels.size();
}
public void updateList(List<Integer> list) {
currentLabelsIds = list;
notifyDataSetChanged();
}
}

View File

@ -2,10 +2,6 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Spanned;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@ -15,40 +11,22 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.vdurmont.emoji.EmojiParser;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.MilestoneActions;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.util.TinyDB;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin;
import io.noties.markwon.core.MarkwonTheme;
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tasklist.TaskListPlugin;
import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.DefaultMediaDecoder;
import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin;
import io.noties.markwon.image.SchemeHandler;
import io.noties.markwon.image.gif.GifMediaDecoder;
import io.noties.markwon.image.svg.SvgMediaDecoder;
import io.noties.markwon.linkify.LinkifyPlugin;
/**
* Author M M Arif
@ -56,369 +34,293 @@ import io.noties.markwon.linkify.LinkifyPlugin;
public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private final int TYPE_LOAD = 0;
private List<Milestones> dataList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false;
private boolean isMoreDataAvailable = true;
private String TAG = StaticGlobalVariables.tagMilestonesAdapter;
private Context context;
private final int TYPE_LOAD = 0;
private List<Milestones> dataList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false;
private boolean isMoreDataAvailable = true;
private String TAG = StaticGlobalVariables.tagMilestonesAdapter;
public MilestonesAdapter(Context context, List<Milestones> dataListMain) {
public MilestonesAdapter(Context context, List<Milestones> dataListMain) {
this.context = context;
this.dataList = dataListMain;
this.context = context;
this.dataList = dataListMain;
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) {
return new MilestonesAdapter.DataHolder(inflater.inflate(R.layout.list_milestones, parent, false));
}
else {
return new MilestonesAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
if(viewType == TYPE_LOAD) {
return new MilestonesAdapter.DataHolder(inflater.inflate(R.layout.list_milestones, parent, false));
}
else {
return new MilestonesAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
@Override
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;
loadMoreListener.onLoadMore();
isLoading = true;
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 TextView msTitle;
private TextView msDescription;
private TextView msOpenIssues;
private TextView msClosedIssues;
private TextView msDueDate;
private ImageView msStatus;
private ProgressBar msProgress;
private TextView milestoneStatus;
private TextView milestoneId;
private TextView msTitle;
private TextView msDescription;
private TextView msOpenIssues;
private TextView msClosedIssues;
private TextView msDueDate;
private ProgressBar msProgress;
private TextView milestoneStatus;
DataHolder(View itemView) {
DataHolder(View itemView) {
super(itemView);
super(itemView);
milestoneId = itemView.findViewById(R.id.milestoneId);
msTitle = itemView.findViewById(R.id.milestoneTitle);
msStatus = itemView.findViewById(R.id.milestoneState);
msDescription = itemView.findViewById(R.id.milestoneDescription);
msOpenIssues = itemView.findViewById(R.id.milestoneIssuesOpen);
msClosedIssues = itemView.findViewById(R.id.milestoneIssuesClosed);
msDueDate = itemView.findViewById(R.id.milestoneDueDate);
msProgress = itemView.findViewById(R.id.milestoneProgress);
ImageView milestonesMenu = itemView.findViewById(R.id.milestonesMenu);
milestoneStatus = itemView.findViewById(R.id.milestoneStatus);
milestoneId = itemView.findViewById(R.id.milestoneId);
msTitle = itemView.findViewById(R.id.milestoneTitle);
msDescription = itemView.findViewById(R.id.milestoneDescription);
msOpenIssues = itemView.findViewById(R.id.milestoneIssuesOpen);
msClosedIssues = itemView.findViewById(R.id.milestoneIssuesClosed);
msDueDate = itemView.findViewById(R.id.milestoneDueDate);
msProgress = itemView.findViewById(R.id.milestoneProgress);
ImageView milestonesMenu = itemView.findViewById(R.id.milestonesMenu);
milestoneStatus = itemView.findViewById(R.id.milestoneStatus);
milestonesMenu.setOnClickListener(v -> {
milestonesMenu.setOnClickListener(v -> {
Context ctx = v.getContext();
int milestoneId_ = Integer.parseInt(milestoneId.getText().toString());
Context ctx = v.getContext();
int milestoneId_ = Integer.parseInt(milestoneId.getText().toString());
@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);
TextView closeMilestone = view.findViewById(R.id.closeMilestone);
TextView openMilestone = view.findViewById(R.id.openMilestone);
TextView closeMilestone = view.findViewById(R.id.closeMilestone);
TextView openMilestone = view.findViewById(R.id.openMilestone);
BottomSheetDialog dialog = new BottomSheetDialog(ctx);
dialog.setContentView(view);
dialog.show();
BottomSheetDialog dialog = new BottomSheetDialog(ctx);
dialog.setContentView(view);
dialog.show();
if(milestoneStatus.getText().toString().equals("open")) {
if(milestoneStatus.getText().toString().equals("open")) {
closeMilestone.setVisibility(View.VISIBLE);
openMilestone.setVisibility(View.GONE);
closeMilestone.setVisibility(View.VISIBLE);
openMilestone.setVisibility(View.GONE);
}
else {
}
else {
closeMilestone.setVisibility(View.GONE);
openMilestone.setVisibility(View.VISIBLE);
closeMilestone.setVisibility(View.GONE);
openMilestone.setVisibility(View.VISIBLE);
}
}
closeMilestone.setOnClickListener(v12 -> {
closeMilestone.setOnClickListener(v12 -> {
MilestoneActions.closeMilestone(ctx, milestoneId_);
dialog.dismiss();
updateAdapter(getAdapterPosition());
MilestoneActions.closeMilestone(ctx, milestoneId_);
dialog.dismiss();
updateAdapter(getAdapterPosition());
});
});
openMilestone.setOnClickListener(v12 -> {
openMilestone.setOnClickListener(v12 -> {
MilestoneActions.openMilestone(ctx, milestoneId_);
dialog.dismiss();
updateAdapter(getAdapterPosition());
MilestoneActions.openMilestone(ctx, milestoneId_);
dialog.dismiss();
updateAdapter(getAdapterPosition());
});
});
});
});
}
@SuppressLint("SetTextI18n")
void bindData(Milestones dataModel) {
final TinyDB tinyDb = new TinyDB(context);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
}
milestoneId.setText(String.valueOf(dataModel.getId()));
milestoneStatus.setText(dataModel.getState());
@SuppressLint("SetTextI18n")
void bindData(Milestones dataModel) {
final Markwon markwon = Markwon.builder(Objects.requireNonNull(context))
.usePlugin(CorePlugin.create())
.usePlugin(ImagesPlugin.create(plugin -> {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = context.getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
context.getPackageName());
final Drawable drawable = context.getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(drawable -> null);
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(context.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(context.getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder
.codeTextColor(tinyDb.getInt("codeBlockColor"))
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(context.getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(context))
.usePlugin(TaskListPlugin.create(context))
.usePlugin(HtmlPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
Spanned msTitle_ = markwon.toMarkdown(dataModel.getTitle());
markwon.setParsedMarkdown(msTitle, msTitle_);
if(dataModel.getState().equals("open")) {
@SuppressLint("ResourceType") int color = Color.parseColor(context.getResources().getString(R.color.releaseStable));
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
//.useFont(Typeface.DEFAULT)
.textColor(context.getResources().getColor(R.color.white))
.fontSize(30)
.toUpperCase()
.width(120)
.height(60)
.endConfig()
.buildRoundRect("open", color, 8);
msStatus.setImageDrawable(drawable);
}
else if(dataModel.getState().equals("closed")) {
@SuppressLint("ResourceType") int color = Color.parseColor(context.getResources().getString(R.color.colorRed));
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
//.useFont(Typeface.DEFAULT)
.textColor(context.getResources().getColor(R.color.white))
.fontSize(30)
.toUpperCase()
.width(140)
.height(60)
.endConfig()
.buildRoundRect("closed", color, 8);
msStatus.setImageDrawable(drawable);
}
if (!dataModel.getDescription().equals("")) {
final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(dataModel.getDescription()));
msDescription.setText(bodyWithMD);
}
else {
msDescription.setText("");
}
msOpenIssues.setText(String.valueOf(dataModel.getOpen_issues()));
msOpenIssues.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneOpenIssues, dataModel.getOpen_issues()), context));
msClosedIssues.setText(String.valueOf(dataModel.getClosed_issues()));
msClosedIssues.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneClosedIssues, dataModel.getClosed_issues()), context));
if ((dataModel.getOpen_issues() + dataModel.getClosed_issues()) > 0) {
if (dataModel.getOpen_issues() == 0) {
msProgress.setProgress(100);
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 100), context));
}
else {
int msCompletion = 100 * dataModel.getClosed_issues() / (dataModel.getOpen_issues() + dataModel.getClosed_issues());
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, msCompletion), context));
msProgress.setProgress(msCompletion);
}
}
else {
msProgress.setProgress(0);
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 0), context));
}
if(dataModel.getDue_on() != null) {
if (timeFormat.equals("normal") || timeFormat.equals("pretty")) {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", new Locale(locale));
Date date = null;
try {
date = formatter.parse(dataModel.getDue_on());
}
catch (ParseException e) {
Log.e(TAG, e.toString());
}
assert date != null;
String dueDate = formatter.format(date);
final TinyDB tinyDb = TinyDB.getInstance(context);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
if(date.before(new Date())) {
msDueDate.setTextColor(context.getResources().getColor(R.color.darkRed));
}
milestoneId.setText(String.valueOf(dataModel.getId()));
milestoneStatus.setText(dataModel.getState());
msDueDate.setText(dueDate);
msDueDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToast(dataModel.getDue_on()), context));
new Markdown(context, dataModel.getTitle(), msTitle);
}
else if (timeFormat.equals("normal1")) {
if(!dataModel.getDescription().equals("")) {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", new Locale(locale));
Date date1 = null;
try {
date1 = formatter.parse(dataModel.getDue_on());
}
catch (ParseException e) {
Log.e(TAG, e.toString());
}
assert date1 != null;
String dueDate = formatter.format(date1);
msDueDate.setText(dueDate);
new Markdown(context, EmojiParser.parseToUnicode(dataModel.getDescription()), msDescription);
}
else {
}
msDescription.setText(context.getString(R.string.milestoneNoDescription));
}
}
else {
msDueDate.setText("");
}
msOpenIssues.setText(context.getString(R.string.milestoneIssueStatusOpen, dataModel.getOpen_issues()));
msClosedIssues.setText(context.getString(R.string.milestoneIssueStatusClosed, dataModel.getClosed_issues()));
}
if((dataModel.getOpen_issues() + dataModel.getClosed_issues()) > 0) {
}
if(dataModel.getOpen_issues() == 0) {
private void updateAdapter(int position) {
msProgress.setProgress(100);
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 100), context));
dataList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, dataList.size());
}
else {
}
int msCompletion = 100 * dataModel.getClosed_issues() / (dataModel.getOpen_issues() + dataModel.getClosed_issues());
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, msCompletion), context));
msProgress.setProgress(msCompletion);
@Override
public int getItemViewType(int position) {
}
if(dataList.get(position).getTitle() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
else {
}
msProgress.setProgress(0);
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 0), context));
@Override
public int getItemCount() {
}
return dataList.size();
if(dataModel.getDue_on() != null) {
}
if(timeFormat.equals("normal") || timeFormat.equals("pretty")) {
static class LoadHolder extends RecyclerView.ViewHolder {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", new Locale(locale));
Date date = null;
LoadHolder(View itemView) {
try {
date = formatter.parse(dataModel.getDue_on());
}
catch(ParseException e) {
Log.e(TAG, e.toString());
}
super(itemView);
}
assert date != null;
String dueDate = formatter.format(date);
}
if(date.before(new Date())) {
msDueDate.setTextColor(context.getResources().getColor(R.color.darkRed));
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
msDueDate.setText(dueDate);
msDueDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToast(dataModel.getDue_on()), context));
isMoreDataAvailable = moreDataAvailable;
}
else if(timeFormat.equals("normal1")) {
}
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", new Locale(locale));
public void notifyDataChanged() {
Date date1 = null;
notifyDataSetChanged();
isLoading = false;
try {
date1 = formatter.parse(dataModel.getDue_on());
}
catch(ParseException e) {
Log.e(TAG, e.toString());
}
}
assert date1 != null;
String dueDate = formatter.format(date1);
msDueDate.setText(dueDate);
public interface OnLoadMoreListener {
}
void onLoadMore();
}
else {
}
msDueDate.setText(context.getString(R.string.milestoneNoDueDate));
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
}
this.loadMoreListener = loadMoreListener;
}
}
private void updateAdapter(int position) {
public void updateList(List<Milestones> list) {
dataList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, dataList.size());
dataList = list;
notifyDataSetChanged();
}
}
@Override
public int getItemViewType(int position) {
if(dataList.get(position).getTitle() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return dataList.size();
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<Milestones> list) {
dataList = list;
notifyDataSetChanged();
}
}

View File

@ -1,190 +0,0 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.TextAppearanceSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.models.MultiSelectModel;
import java.util.ArrayList;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatCheckBox;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
/**
* Author com.github.abumoallim, modified by M M Arif
*/
public class MutliSelectAdapter extends RecyclerView.Adapter<MutliSelectAdapter.MultiSelectDialogViewHolder> {
private ArrayList<MultiSelectModel> mDataSet;
private String mSearchQuery = "";
private Context mContext;
public MutliSelectAdapter(ArrayList<MultiSelectModel> dataSet, Context context) {
this.mDataSet = dataSet;
this.mContext = context;
}
@NonNull
@Override
public MultiSelectDialogViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.multi_select_item, parent, false);
return new MultiSelectDialogViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final MultiSelectDialogViewHolder holder, int position) {
if (!mSearchQuery.equals("") && mSearchQuery.length() > 1) {
setHighlightedText(position, holder.dialog_name_item);
} else {
holder.dialog_name_item.setText(mDataSet.get(position).getName());
}
if (mDataSet.get(position).getSelected()) {
if (!MultiSelectDialog.selectedIdsForCallback.contains(mDataSet.get(position).getId())) {
MultiSelectDialog.selectedIdsForCallback.add(mDataSet.get(position).getId());
}
}
if (checkForSelection(mDataSet.get(position).getId())) {
holder.dialog_item_checkbox.setChecked(true);
} else {
holder.dialog_item_checkbox.setChecked(false);
}
/*holder.dialog_item_checkbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (holder.dialog_item_checkbox.isChecked()) {
MultiSelectDialog.selectedIdsForCallback.add(mDataSet.get(holder.getAdapterPosition()).getId());
holder.dialog_item_checkbox.setChecked(true);
} else {
removeFromSelection(mDataSet.get(holder.getAdapterPosition()).getId());
holder.dialog_item_checkbox.setChecked(false);
}
}
});*/
holder.main_container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!holder.dialog_item_checkbox.isChecked()) {
MultiSelectDialog.selectedIdsForCallback.add(mDataSet.get(holder.getAdapterPosition()).getId());
holder.dialog_item_checkbox.setChecked(true);
mDataSet.get(holder.getAdapterPosition()).setSelected(true);
notifyItemChanged(holder.getAdapterPosition());
} else {
removeFromSelection(mDataSet.get(holder.getAdapterPosition()).getId());
holder.dialog_item_checkbox.setChecked(false);
mDataSet.get(holder.getAdapterPosition()).setSelected(false);
notifyItemChanged(holder.getAdapterPosition());
}
}
});
}
private void setHighlightedText(int position, TextView textview) {
String name = mDataSet.get(position).getName();
SpannableString str = new SpannableString(name);
int endLength = name.toLowerCase().indexOf(mSearchQuery) + mSearchQuery.length();
ColorStateList highlightedColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{ContextCompat.getColor(mContext, R.color.colorAccent)});
TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan(null, Typeface.NORMAL, -1, highlightedColor, null);
str.setSpan(textAppearanceSpan, name.toLowerCase().indexOf(mSearchQuery), endLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText(str);
}
private void removeFromSelection(Integer id) {
for (int i = 0; i < MultiSelectDialog.selectedIdsForCallback.size(); i++) {
if (id.equals(MultiSelectDialog.selectedIdsForCallback.get(i))) {
MultiSelectDialog.selectedIdsForCallback.remove(i);
}
}
}
private boolean checkForSelection(Integer id) {
for (int i = 0; i < MultiSelectDialog.selectedIdsForCallback.size(); i++) {
if (id.equals(MultiSelectDialog.selectedIdsForCallback.get(i))) {
return true;
}
}
return false;
}
/*//get selected name string separated by coma
public String getDataString() {
String data = "";
for (int i = 0; i < mDataSet.size(); i++) {
if (checkForSelection(mDataSet.get(i).getId())) {
data = data + ", " + mDataSet.get(i).getName();
}
}
if (data.length() > 0) {
return data.substring(1);
} else {
return "";
}
}
//get selected name ararylist
public ArrayList<String> getSelectedNameList() {
ArrayList<String> names = new ArrayList<>();
for (int i = 0; i < mDataSet.size(); i++) {
if (checkForSelection(mDataSet.get(i).getId())) {
names.add(mDataSet.get(i).getName());
}
}
// return names.toArray(new String[names.size()]);
return names;
}*/
@Override
public int getItemCount() {
return mDataSet.size();
}
public void setData(ArrayList<MultiSelectModel> data, String query, MutliSelectAdapter mutliSelectAdapter) {
this.mDataSet = data;
this.mSearchQuery = query;
mutliSelectAdapter.notifyDataSetChanged();
}
class MultiSelectDialogViewHolder extends RecyclerView.ViewHolder {
private TextView dialog_name_item;
private AppCompatCheckBox dialog_item_checkbox;
private LinearLayout main_container;
MultiSelectDialogViewHolder(View view) {
super(view);
dialog_name_item = view.findViewById(R.id.dialog_item_name);
dialog_item_checkbox = view.findViewById(R.id.dialog_item_checkbox);
main_container = view.findViewById(R.id.main_container);
}
}
}

View File

@ -1,6 +1,8 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
@ -11,26 +13,31 @@ import android.widget.CheckBox;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.RepoForksActivity;
import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
@ -40,258 +47,321 @@ import retrofit2.Callback;
public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.MyReposViewHolder> implements Filterable {
private List<UserRepositories> reposList;
private Context mCtx;
private List<UserRepositories> reposListFull;
private List<UserRepositories> reposList;
private Context mCtx;
private List<UserRepositories> reposListFull;
static class MyReposViewHolder extends RecyclerView.ViewHolder {
static class MyReposViewHolder extends RecyclerView.ViewHolder {
private ImageView imageAvatar;
private TextView repoName;
private TextView repoDescription;
private TextView repoFullName;
private ImageView repoPrivatePublic;
private TextView repoStars;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private CheckBox isRepoAdmin;
private ImageView imageAvatar;
private TextView repoName;
private TextView repoDescription;
private TextView repoFullName;
private ImageView repoPrivatePublic;
private TextView repoStars;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private CheckBox isRepoAdmin;
private LinearLayout archiveRepo;
private TextView repoBranch;
private TextView htmlUrl;
private MyReposViewHolder(View itemView) {
super(itemView);
repoName = itemView.findViewById(R.id.repoName);
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);
private MyReposViewHolder(View itemView) {
itemView.setOnClickListener(v -> {
super(itemView);
repoName = itemView.findViewById(R.id.repoName);
repoDescription = itemView.findViewById(R.id.repoDescription);
imageAvatar = itemView.findViewById(R.id.imageAvatar);
repoFullName = itemView.findViewById(R.id.repoFullName);
repoPrivatePublic = itemView.findViewById(R.id.imageRepoType);
repoStars = itemView.findViewById(R.id.repoStars);
repoForks = itemView.findViewById(R.id.repoForks);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
repoBranch = itemView.findViewById(R.id.repoBranch);
htmlUrl = itemView.findViewById(R.id.htmlUrl);
Context context = v.getContext();
itemView.setOnClickListener(v -> {
Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", repoFullName.getText().toString());
Context context = v.getContext();
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putString("repoType", repoType.getText().toString());
//tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", repoFullName.getText().toString());
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
String[] parts = repoFullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putString("repoType", repoType.getText().toString());
//tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
tinyDb.putString("repoBranch", repoBranch.getText().toString());
WatchInfo watch = new WatchInfo();
String[] parts = repoFullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<WatchInfo> call;
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context);
call = RetrofitClient.getInstance(instanceUrl, context).getApiInterface().checkRepoWatchStatus(token, repoOwner, repoName);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
call.enqueue(new Callback<WatchInfo>() {
if(count == 0) {
@Override
public void onResponse(@NonNull Call<WatchInfo> call, @NonNull retrofit2.Response<WatchInfo> response) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
if(response.isSuccessful()) {
}
else {
assert response.body() != null;
tinyDb.putBoolean("repoWatch", response.body().getSubscribed());
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
} else {
}
tinyDb.putBoolean("repoWatch", false);
//store if user is watching this repo
{
if(response.code() != 404) {
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
Toasty.info(context, context.getString(R.string.genericApiStatusError));
WatchInfo watch = new WatchInfo();
}
Call<WatchInfo> call;
}
call = RetrofitClient.getApiInterface(context).checkRepoWatchStatus(token, repoOwner, repoName);
}
call.enqueue(new Callback<WatchInfo>() {
@Override
public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) {
@Override
public void onResponse(@NonNull Call<WatchInfo> call, @NonNull retrofit2.Response<WatchInfo> response) {
tinyDb.putBoolean("repoWatch", false);
Toasty.info(context, context.getString(R.string.genericApiStatusError));
if(response.isSuccessful()) {
}
});
}
assert response.body() != null;
tinyDb.putBoolean("repoWatch", response.body().getSubscribed());
context.startActivity(intent);
}
else {
});
tinyDb.putBoolean("repoWatch", false);
reposDropdownMenu.setOnClickListener(v -> {
if(response.code() != 404) {
final Context context = v.getContext();
Toasty.error(context, context.getString(R.string.genericApiStatusError));
@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 bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader);
}
bottomSheetHeader.setText(repoFullName.getText());
BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view);
dialog.show();
}
repoOpenInBrowser.setOnClickListener(openInBrowser -> {
@Override
public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) {
Intent intentOpenInBrowser = new Intent(context, OpenRepoInBrowserActivity.class);
intentOpenInBrowser.putExtra("repoFullNameBrowser", repoFullName.getText());
context.startActivity(intentOpenInBrowser);
dialog.dismiss();
tinyDb.putBoolean("repoWatch", false);
Toasty.error(context, context.getString(R.string.genericApiStatusError));
});
}
});
repoStargazers.setOnClickListener(stargazers -> {
}
Intent intent = new Intent(context, RepoStargazersActivity.class);
intent.putExtra("repoFullNameForStars", repoFullName.getText());
context.startActivity(intent);
dialog.dismiss();
context.startActivity(intent);
});
});
repoWatchers.setOnClickListener(watchers -> {
reposDropdownMenu.setOnClickListener(v -> {
Intent intentW = new Intent(context, RepoWatchersActivity.class);
intentW.putExtra("repoFullNameForWatchers", repoFullName.getText());
context.startActivity(intentW);
dialog.dismiss();
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();
public MyReposListAdapter(Context mCtx, List<UserRepositories> reposListMain) {
this.mCtx = mCtx;
this.reposList = reposListMain;
reposListFull = new ArrayList<>(reposList);
}
repoCopyUrl.setOnClickListener(openInBrowser -> {
@NonNull
@Override
public MyReposListAdapter.MyReposViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_repositories, parent, false);
return new MyReposListAdapter.MyReposViewHolder(v);
}
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(context).getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("repoUrl", htmlUrl.getText().toString());
assert clipboard != null;
clipboard.setPrimaryClip(clip);
@Override
public void onBindViewHolder(@NonNull MyReposListAdapter.MyReposViewHolder holder, int position) {
Toasty.info(context, context.getString(R.string.copyIssueUrlToastMsg));
dialog.dismiss();
});
UserRepositories currentItem = reposList.get(position);
holder.repoDescription.setVisibility(View.GONE);
repoOpenInBrowser.setOnClickListener(openInBrowser -> {
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
String firstCharacter = String.valueOf(currentItem.getName().charAt(0));
Intent intentOpenInBrowser = new Intent(context, OpenRepoInBrowserActivity.class);
intentOpenInBrowser.putExtra("repoFullNameBrowser", repoFullName.getText());
context.startActivity(intentOpenInBrowser);
dialog.dismiss();
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.useFont(Typeface.DEFAULT)
.fontSize(18)
.toUpperCase()
.width(28)
.height(28)
.endConfig()
.buildRoundRect(firstCharacter, color, 3);
});
if (currentItem.getAvatar_url() != null) {
if (!currentItem.getAvatar_url().equals("")) {
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.imageAvatar);
} else {
holder.imageAvatar.setImageDrawable(drawable);
}
}
else {
holder.imageAvatar.setImageDrawable(drawable);
}
repoStargazers.setOnClickListener(stargazers -> {
holder.repoName.setText(currentItem.getName());
if (!currentItem.getDescription().equals("")) {
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.repoFullName.setText(currentItem.getFullname());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_public);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count());
holder.repoOpenIssuesCount.setText(currentItem.getOpen_issues_count());
Intent intent = new Intent(context, RepoStargazersActivity.class);
intent.putExtra("repoFullNameForStars", repoFullName.getText());
context.startActivity(intent);
dialog.dismiss();
if(holder.isRepoAdmin == null) {
holder.isRepoAdmin = new CheckBox(mCtx);
}
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
});
}
repoWatchers.setOnClickListener(watchers -> {
@Override
public int getItemCount() {
return reposList.size();
}
Intent intentW = new Intent(context, RepoWatchersActivity.class);
intentW.putExtra("repoFullNameForWatchers", repoFullName.getText());
context.startActivity(intentW);
dialog.dismiss();
@Override
public Filter getFilter() {
return myReposFilter;
}
});
private Filter myReposFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<UserRepositories> filteredList = new ArrayList<>();
repoForksList.setOnClickListener(forks -> {
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(reposListFull);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
Intent intentW = new Intent(context, RepoForksActivity.class);
intentW.putExtra("repoFullNameForForks", repoFullName.getText());
context.startActivity(intentW);
dialog.dismiss();
for (UserRepositories item : reposListFull) {
if (item.getFullname().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
});
FilterResults results = new FilterResults();
results.values = filteredList;
});
return results;
}
}
}
public MyReposListAdapter(Context mCtx, List<UserRepositories> reposListMain) {
this.mCtx = mCtx;
this.reposList = reposListMain;
reposListFull = new ArrayList<>(reposList);
}
@NonNull
@Override
public MyReposListAdapter.MyReposViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_repositories, parent, false);
return new MyReposListAdapter.MyReposViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull MyReposListAdapter.MyReposViewHolder holder, int position) {
UserRepositories currentItem = reposList.get(position);
holder.repoDescription.setVisibility(View.GONE);
holder.repoBranch.setText(currentItem.getDefault_branch());
holder.htmlUrl.setText(currentItem.getHtml_url());
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
String firstCharacter = String.valueOf(currentItem.getName().charAt(0));
TextDrawable drawable = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT).fontSize(18).toUpperCase().width(28).height(28).endConfig().buildRoundRect(firstCharacter, color, 3);
if(currentItem.getAvatar_url() != null) {
if(!currentItem.getAvatar_url().equals("")) {
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.imageAvatar);
}
else {
holder.imageAvatar.setImageDrawable(drawable);
}
}
else {
holder.imageAvatar.setImageDrawable(drawable);
}
holder.repoName.setText(currentItem.getName());
if(!currentItem.getDescription().equals("")) {
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.repoFullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublic.setVisibility(View.GONE);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count());
holder.repoOpenIssuesCount.setText(currentItem.getOpen_issues_count());
if(holder.isRepoAdmin == null) {
holder.isRepoAdmin = new CheckBox(mCtx);
}
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
}
@Override
public int getItemCount() {
return reposList.size();
}
@Override
public Filter getFilter() {
return myReposFilter;
}
private Filter myReposFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<UserRepositories> filteredList = new ArrayList<>();
if(constraint == null || constraint.length() == 0) {
filteredList.addAll(reposListFull);
}
else {
String filterPattern = constraint.toString().toLowerCase().trim();
for(UserRepositories item : reposListFull) {
if(item.getFullName().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
reposList.clear();
reposList.addAll((List) results.values);
notifyDataSetChanged();
}
};
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
reposList.clear();
reposList.addAll((List) results.values);
notifyDataSetChanged();
}
};
}

View File

@ -0,0 +1,166 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.NotificationThread;
import java.util.List;
/**
* Author opyale
*/
public class NotificationsAdapter extends RecyclerView.Adapter<NotificationsAdapter.NotificationsViewHolder> {
private Context context;
private List<NotificationThread> notificationThreads;
private OnMoreClickedListener onMoreClickedListener;
private OnNotificationClickedListener onNotificationClickedListener;
private TinyDB tinyDb;
public NotificationsAdapter(Context context, List<NotificationThread> notificationThreads, OnMoreClickedListener onMoreClickedListener, OnNotificationClickedListener onNotificationClickedListener) {
this.tinyDb = TinyDB.getInstance(context);
this.context = context;
this.notificationThreads = notificationThreads;
this.onMoreClickedListener = onMoreClickedListener;
this.onNotificationClickedListener = onNotificationClickedListener;
}
static class NotificationsViewHolder extends RecyclerView.ViewHolder {
private LinearLayout frame;
private TextView subject;
private TextView repository;
private ImageView typePr;
private ImageView typeIssue;
private ImageView typeUnknown;
private ImageView pinned;
private ImageView more;
public NotificationsViewHolder(@NonNull View itemView) {
super(itemView);
frame = itemView.findViewById(R.id.frame);
subject = itemView.findViewById(R.id.subject);
repository = itemView.findViewById(R.id.repository);
typePr = itemView.findViewById(R.id.typePr);
typeIssue = itemView.findViewById(R.id.typeIssue);
typeUnknown = itemView.findViewById(R.id.typeUnknown);
pinned = itemView.findViewById(R.id.pinned);
more = itemView.findViewById(R.id.more);
}
}
@NonNull
@Override
public NotificationsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.list_notifications, parent, false);
return new NotificationsAdapter.NotificationsViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull NotificationsViewHolder holder, int position) {
NotificationThread notificationThread = notificationThreads.get(position);
String url = notificationThread.getSubject().getUrl();
String subjectId = "<font color='" + context.getResources().getColor(R.color.lightGray) + "'>" + context.getResources()
.getString(R.string.hash) + url.substring(url.lastIndexOf("/") + 1) + "</font>";
holder.subject.setText(Html.fromHtml(subjectId + " " + notificationThread.getSubject().getTitle()));
holder.repository.setText(notificationThread.getRepository().getFullName());
if(notificationThread.isPinned()) {
holder.pinned.setVisibility(View.VISIBLE);
}
else {
holder.pinned.setVisibility(View.GONE);
}
switch(notificationThread.getSubject().getType()) {
case "Pull":
holder.typePr.setVisibility(View.VISIBLE);
holder.typeIssue.setVisibility(View.GONE);
holder.typeUnknown.setVisibility(View.GONE);
break;
case "Issue":
holder.typePr.setVisibility(View.GONE);
holder.typeIssue.setVisibility(View.VISIBLE);
holder.typeUnknown.setVisibility(View.GONE);
break;
default:
holder.typePr.setVisibility(View.GONE);
holder.typeIssue.setVisibility(View.GONE);
holder.typeUnknown.setVisibility(View.VISIBLE);
break;
}
holder.frame.setOnClickListener(v -> {
onNotificationClickedListener.onNotificationClicked(notificationThread);
String[] parts = notificationThread.getRepository().getFullName().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
});
holder.more.setOnClickListener(v -> onMoreClickedListener.onMoreClicked(notificationThread));
}
@Override
public int getItemCount() {
return notificationThreads.size();
}
public interface OnNotificationClickedListener {
void onNotificationClicked(NotificationThread notificationThread);
}
public interface OnMoreClickedListener {
void onMoreClicked(NotificationThread notificationThread);
}
}

View File

@ -1,7 +1,5 @@
package org.mian.gitnex.adapters;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
@ -12,12 +10,14 @@ import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OrganizationDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.models.UserOrganizations;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserOrganizations;
import java.util.ArrayList;
import java.util.List;
@ -53,7 +53,7 @@ public class OrganizationsListAdapter extends RecyclerView.Adapter<Organizations
Intent intent = new Intent(context, OrganizationDetailActivity.class);
intent.putExtra("orgName", mTextView1.getText().toString());
TinyDB tinyDb = new TinyDB(context);
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("orgName", mTextView1.getText().toString());
tinyDb.putString("organizationId", organizationId.getText().toString());
tinyDb.putBoolean("organizationAction", true);

View File

@ -58,7 +58,7 @@ public class ProfileEmailsAdapter extends RecyclerView.Adapter<ProfileEmailsAdap
if(currentItem.getPrimary()) {
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.textColor(mCtx.getResources().getColor(R.color.white))
.textColor(mCtx.getResources().getColor(R.color.colorWhite))
.fontSize(36)
.width(220)
.height(60)

View File

@ -18,8 +18,8 @@ import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.PullRequests;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import java.util.Locale;
@ -130,13 +130,13 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
intent.putExtra("prMergeable", prMergeable.getText());
intent.putExtra("prHeadBranch", prHeadBranch.getText());
TinyDB tinyDb = new TinyDB(context);
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", "pr");
tinyDb.putString("issueType", "Pull");
context.startActivity(intent);
});
@ -149,13 +149,13 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
intent.putExtra("prMergeable", prMergeable.getText());
intent.putExtra("prHeadBranch", prHeadBranch.getText());
TinyDB tinyDb = new TinyDB(context);
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", "pr");
tinyDb.putString("issueType", "Pull");
context.startActivity(intent);
});
@ -165,7 +165,7 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
@SuppressLint("SetTextI18n")
void bindData(PullRequests prModel) {
final TinyDB tinyDb = new TinyDB(context);
final TinyDB tinyDb = TinyDB.getInstance(context);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
@ -188,9 +188,18 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
prNumber.setText(String.valueOf(prModel.getNumber()));
prMergeable.setText(String.valueOf(prModel.isMergeable()));
prHeadBranch.setText(prModel.getHead().getRef());
prIsFork.setText(String.valueOf(prModel.getHead().getRepo().isFork()));
prForkFullName.setText(prModel.getHead().getRepo().getFull_name());
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 {
// pull was done from a deleted fork
prIsFork.setText("true");
prForkFullName.setText(context.getString(R.string.prDeletedFrok));
}
}
prCommentsCount.setText(String.valueOf(prModel.getComments()));
prCreatedTime.setText(TimeHelper.formatTime(prModel.getCreated_at(), new Locale(locale), timeFormat, context));

View File

@ -1,44 +1,28 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Html;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.vdurmont.emoji.EmojiParser;
import org.mian.gitnex.R;
import org.mian.gitnex.models.Releases;
import org.mian.gitnex.util.TinyDB;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin;
import io.noties.markwon.core.MarkwonTheme;
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tasklist.TaskListPlugin;
import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.AsyncDrawable;
import io.noties.markwon.image.DefaultMediaDecoder;
import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin;
import io.noties.markwon.image.SchemeHandler;
import io.noties.markwon.image.gif.GifMediaDecoder;
import io.noties.markwon.image.svg.SvgMediaDecoder;
import io.noties.markwon.linkify.LinkifyPlugin;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Releases;
import java.util.List;
import java.util.Locale;
/**
* Author M M Arif
@ -49,25 +33,44 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
private List<Releases> releasesList;
private Context mCtx;
static class ReleasesViewHolder extends RecyclerView.ViewHolder {
static class ReleasesViewHolder extends RecyclerView.ViewHolder {
private ImageView releaseType;
private TextView releaseTitle;
private TextView releaseDescription;
private TextView releaseDownload;
private TextView releaseZipDownload;
private TextView releaseTarDownload;
private TextView releaseType;
private TextView releaseName;
private ImageView authorAvatar;
private TextView authorName;
private TextView releaseTag;
private TextView releaseCommitSha;
private TextView releaseDate;
private TextView releaseBodyContent;
private LinearLayout downloadFrame;
private RelativeLayout downloads;
private TextView releaseZipDownload;
private TextView releaseTarDownload;
private ImageView downloadDropdownIcon;
private RecyclerView downloadList;
private ReleasesViewHolder(View itemView) {
super(itemView);
releaseType = itemView.findViewById(R.id.releaseType);
releaseTitle = itemView.findViewById(R.id.releaseTitle);
releaseDescription = itemView.findViewById(R.id.releaseDescription);
releaseZipDownload = itemView.findViewById(R.id.releaseZipDownload);
releaseTarDownload = itemView.findViewById(R.id.releaseTarDownload);
releaseTag = itemView.findViewById(R.id.releaseTag);
releaseType = itemView.findViewById(R.id.releaseType);
releaseName = itemView.findViewById(R.id.releaseName);
authorAvatar = itemView.findViewById(R.id.authorAvatar);
authorName = itemView.findViewById(R.id.authorName);
releaseTag = itemView.findViewById(R.id.releaseTag);
releaseCommitSha = itemView.findViewById(R.id.releaseCommitSha);
releaseDate = itemView.findViewById(R.id.releaseDate);
releaseBodyContent = itemView.findViewById(R.id.releaseBodyContent);
downloadFrame = itemView.findViewById(R.id.downloadFrame);
downloads = itemView.findViewById(R.id.downloads);
releaseZipDownload = itemView.findViewById(R.id.releaseZipDownload);
releaseTarDownload = itemView.findViewById(R.id.releaseTarDownload);
downloadDropdownIcon = itemView.findViewById(R.id.downloadDropdownIcon);
downloadList = itemView.findViewById(R.id.downloadList);
downloadList.setHasFixedSize(true);
downloadList.setLayoutManager(new LinearLayoutManager(itemView.getContext()));
}
}
@ -87,110 +90,68 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
@Override
public void onBindViewHolder(@NonNull ReleasesAdapter.ReleasesViewHolder holder, int position) {
final TinyDB tinyDb = new TinyDB(mCtx);
final TinyDB tinyDb = TinyDB.getInstance(mCtx);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
Releases currentItem = releasesList.get(position);
holder.releaseTitle.setText(currentItem.getName());
holder.releaseName.setText(currentItem.getName());
if(!currentItem.getTag_name().equals("")) {
holder.releaseTag.setText(mCtx.getResources().getString(R.string.releaseTag, currentItem.getTag_name()));
}
else {
holder.releaseTag.setVisibility(View.GONE);
}
if(currentItem.isPrerelease()) {
holder.releaseType.setBackgroundResource(R.drawable.shape_pre_release);
holder.releaseType.setText(R.string.releaseTypePre);
}
else if(currentItem.isDraft()) {
holder.releaseType.setVisibility(View.GONE);
}
else {
holder.releaseType.setBackgroundResource(R.drawable.shape_stable_release);
holder.releaseType.setText(R.string.releaseTypeStable);
}
if(currentItem.isPrerelease()) {
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
//.useFont(Typeface.DEFAULT)
.textColor(mCtx.getResources().getColor(R.color.white))
.fontSize(34)
.width(260)
.height(60)
.endConfig()
.buildRoundRect(mCtx.getResources().getString(R.string.releaseTypePre), mCtx.getResources().getColor(R.color.releasePre), 8);
holder.releaseType.setImageDrawable(drawable);
}
else {
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
//.useFont(Typeface.DEFAULT)
.textColor(mCtx.getResources().getColor(R.color.white))
.fontSize(34)
.width(260)
.height(60)
.endConfig()
.buildRoundRect(mCtx.getResources().getString(R.string.releaseTypeStable), mCtx.getResources().getColor(R.color.releaseStable), 8);
holder.releaseType.setImageDrawable(drawable);
}
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);
}
final Markwon markwon = Markwon.builder(Objects.requireNonNull(mCtx))
.usePlugin(CorePlugin.create())
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
@Override
public void configureImages(@NonNull ImagesPlugin plugin) {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
holder.authorName.setText(mCtx.getResources().getString(R.string.releasePublishedBy, currentItem.getAuthor().getUsername()));
final int resourceId = mCtx.getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
mCtx.getPackageName());
if(currentItem.getTag_name() != null) {
holder.releaseTag.setText(currentItem.getTag_name());
}
final Drawable drawable = mCtx.getDrawable(resourceId);
if(currentItem.getPublished_at() != null) {
holder.releaseDate.setText(TimeHelper.formatTime(currentItem.getPublished_at(), new Locale(locale), timeFormat, mCtx));
}
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
@Nullable
@Override
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
return null;
}
});
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder
.codeTextColor(tinyDb.getInt("codeBlockColor"))
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(mCtx.getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(mCtx))
.usePlugin(TaskListPlugin.create(mCtx))
.usePlugin(HtmlPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(currentItem.getBody()));
if(timeFormat.equals("pretty")) {
holder.releaseDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getPublished_at()), mCtx));
}
if(!currentItem.getBody().equals("")) {
markwon.setParsedMarkdown(holder.releaseDescription, bodyWithMD);
new Markdown(mCtx, currentItem.getBody(), holder.releaseBodyContent);
}
else {
holder.releaseDescription.setVisibility(View.GONE);
holder.releaseBodyContent.setText(R.string.noReleaseBodyContent);
}
holder.downloadFrame.setOnClickListener(v -> {
if(holder.downloads.getVisibility() == View.GONE) {
holder.downloadDropdownIcon.setImageResource(R.drawable.ic_chevron_down);
holder.downloads.setVisibility(View.VISIBLE);
}
else {
holder.downloadDropdownIcon.setImageResource(R.drawable.ic_chevron_right);
holder.downloads.setVisibility(View.GONE);
}
});
holder.releaseZipDownload.setText(
Html.fromHtml("<a href='" + currentItem.getZipball_url() + "'>" + mCtx.getResources().getString(R.string.zipArchiveDownloadReleasesTab) + "</a> "));
holder.releaseZipDownload.setMovementMethod(LinkMovementMethod.getInstance());
@ -199,6 +160,9 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
Html.fromHtml("<a href='" + currentItem.getTarball_url() + "'>" + mCtx.getResources().getString(R.string.tarArchiveDownloadReleasesTab) + "</a> "));
holder.releaseTarDownload.setMovementMethod(LinkMovementMethod.getInstance());
ReleasesDownloadsAdapter adapter = new ReleasesDownloadsAdapter(currentItem.getAssets());
holder.downloadList.setAdapter(adapter);
}
@Override

View File

@ -0,0 +1,68 @@
package org.mian.gitnex.adapters;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.models.Releases;
import java.util.List;
/**
* Author M M Arif
**/
public class ReleasesDownloadsAdapter extends RecyclerView.Adapter<ReleasesDownloadsAdapter.ReleasesDownloadsViewHolder> {
private List<Releases.assetsObject> releasesDownloadsList;
static class ReleasesDownloadsViewHolder extends RecyclerView.ViewHolder {
private TextView downloadName;
private ReleasesDownloadsViewHolder(View itemView) {
super(itemView);
downloadName = itemView.findViewById(R.id.downloadName);
}
}
ReleasesDownloadsAdapter(List<Releases.assetsObject> releasesDownloadsMain) {
this.releasesDownloadsList = releasesDownloadsMain;
}
@NonNull
@Override
public ReleasesDownloadsAdapter.ReleasesDownloadsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_releases_downloads, parent, false);
return new ReleasesDownloadsAdapter.ReleasesDownloadsViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull ReleasesDownloadsAdapter.ReleasesDownloadsViewHolder holder, int position) {
Releases.assetsObject currentItem = releasesDownloadsList.get(position);
if(currentItem.getName() != null) {
holder.downloadName.setText(
Html.fromHtml("<a href='" + currentItem.getBrowser_download_url() + "'>" + currentItem.getName() + "</a> "));
holder.downloadName.setMovementMethod(LinkMovementMethod.getInstance());
}
}
@Override
public int getItemCount() {
return releasesDownloadsList.size();
}
}

View File

@ -0,0 +1,395 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.RepoForksActivity;
import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context ctx;
private final int TYPE_LOAD = 0;
private List<UserRepositories> forksList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false;
private boolean isMoreDataAvailable = true;
public RepoForksAdapter(Context ctx, List<UserRepositories> forksListMain) {
this.ctx = ctx;
this.forksList = forksListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(ctx);
if(viewType == TYPE_LOAD) {
return new RepoForksAdapter.ForksHolder(inflater.inflate(R.layout.list_repositories, parent, false));
}
else {
return new LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((RepoForksAdapter.ForksHolder) holder).bindData(forksList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(forksList.get(position).getName() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return forksList.size();
}
class ForksHolder extends RecyclerView.ViewHolder {
private ImageView image;
private TextView repoName;
private TextView repoDescription;
private TextView fullName;
private CheckBox isRepoAdmin;
private ImageView repoPrivatePublic;
private TextView repoStars;
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private LinearLayout archiveRepo;
private TextView repoBranch;
private ImageView reposDropdownMenu;
ForksHolder(View itemView) {
super(itemView);
repoName = itemView.findViewById(R.id.repoName);
repoDescription = itemView.findViewById(R.id.repoDescription);
isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin);
image = itemView.findViewById(R.id.imageAvatar);
fullName = itemView.findViewById(R.id.repoFullName);
repoPrivatePublic = itemView.findViewById(R.id.imageRepoType);
repoStars = itemView.findViewById(R.id.repoStars);
repoForks = itemView.findViewById(R.id.repoForks);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
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")
void bindData(UserRepositories forksModel) {
repoDescription.setVisibility(View.GONE);
repoBranch.setText(forksModel.getDefault_branch());
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(forksModel.getName());
String firstCharacter = String.valueOf(forksModel.getName().charAt(0));
TextDrawable drawable = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT).fontSize(18).toUpperCase().width(28).height(28)
.endConfig().buildRoundRect(firstCharacter, color, 3);
if(forksModel.getAvatar_url() != null) {
if(!forksModel.getAvatar_url().equals("")) {
PicassoService.getInstance(ctx).get().load(forksModel.getAvatar_url()).placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(image);
}
else {
image.setImageDrawable(drawable);
}
}
else {
image.setImageDrawable(drawable);
}
repoName.setText(forksModel.getName());
if(!forksModel.getDescription().equals("")) {
repoDescription.setVisibility(View.VISIBLE);
repoDescription.setText(forksModel.getDescription());
}
fullName.setText(forksModel.getFullName());
if(forksModel.getPrivateFlag()) {
repoPrivatePublic.setImageResource(R.drawable.ic_lock);
repoType.setText(R.string.strPrivate);
}
else {
repoPrivatePublic.setVisibility(View.GONE);
repoType.setText(R.string.strPublic);
}
repoStars.setText(forksModel.getStars_count());
repoForks.setText(forksModel.getForks_count());
repoOpenIssuesCount.setText(forksModel.getOpen_issues_count());
if(isRepoAdmin == null) {
isRepoAdmin = new CheckBox(ctx);
}
isRepoAdmin.setChecked(forksModel.getPermissions().isAdmin());
if(forksModel.isArchived()) {
archiveRepo.setVisibility(View.VISIBLE);
}
else {
archiveRepo.setVisibility(View.GONE);
}
itemView.setOnClickListener(v -> {
Context context = v.getContext();
TextView repoFullName = v.findViewById(R.id.repoFullName);
TextView repoType_ = v.findViewById(R.id.repoType);
Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", repoFullName.getText().toString());
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putString("repoType", repoType_.getText().toString());
//tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
tinyDb.putString("repoBranch", repoBranch.getText().toString());
String[] parts = repoFullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
//store if user is watching this repo
{
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchInfo watch = new WatchInfo();
Call<WatchInfo> call;
call = RetrofitClient.getApiInterface(context).checkRepoWatchStatus(token, repoOwner, repoName);
call.enqueue(new Callback<WatchInfo>() {
@Override
public void onResponse(@NonNull Call<WatchInfo> call, @NonNull retrofit2.Response<WatchInfo> response) {
if(response.isSuccessful()) {
assert response.body() != null;
tinyDb.putBoolean("repoWatch", response.body().getSubscribed());
}
else {
tinyDb.putBoolean("repoWatch", false);
if(response.code() != 404) {
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
}
}
@Override
public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) {
tinyDb.putBoolean("repoWatch", false);
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
});
}
context.startActivity(intent);
});
reposDropdownMenu.setOnClickListener(v -> {
final Context context = v.getContext();
@SuppressLint("InflateParams") View view = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_repository_in_list, null);
TextView repoOpenInBrowser = view.findViewById(R.id.repoOpenInBrowser);
TextView repoStargazers = view.findViewById(R.id.repoStargazers);
TextView repoWatchers = view.findViewById(R.id.repoWatchers);
TextView repoForksList = view.findViewById(R.id.repoForksList);
TextView 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();
});
});
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(RepoForksAdapter.OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<UserRepositories> list) {
forksList = list;
notifyDataSetChanged();
}
}

View File

@ -12,8 +12,8 @@ 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.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
/**
@ -81,7 +81,7 @@ public class RepoStargazersAdapter extends BaseAdapter {
UserInfo currentItem = stargazersList.get(position);
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.memberAvatar);
final TinyDB tinyDb = new TinyDB(mCtx);
final TinyDB tinyDb = TinyDB.getInstance(mCtx);
Typeface myTypeface;
switch(tinyDb.getInt("customFontId", -1)) {
@ -109,13 +109,6 @@ public class RepoStargazersAdapter extends BaseAdapter {
viewHolder.memberName.setTypeface(myTypeface);
}
if(tinyDb.getInt("themeId") == 1) { //light
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.lightThemeTextColor));
}
else { // dark
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.white));
}
}
}

View File

@ -12,8 +12,8 @@ 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.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
/**
@ -81,7 +81,7 @@ public class RepoWatchersAdapter extends BaseAdapter {
UserInfo currentItem = watchersList.get(position);
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.memberAvatar);
final TinyDB tinyDb = new TinyDB(mCtx);
final TinyDB tinyDb = TinyDB.getInstance(mCtx);
Typeface myTypeface;
switch(tinyDb.getInt("customFontId", -1)) {
@ -109,13 +109,6 @@ public class RepoWatchersAdapter extends BaseAdapter {
viewHolder.memberName.setTypeface(myTypeface);
}
if(tinyDb.getInt("themeId") == 1) { //light
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.lightThemeTextColor));
}
else { // dark
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.white));
}
}
}

View File

@ -1,6 +1,8 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
@ -11,6 +13,7 @@ import android.widget.CheckBox;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
@ -20,17 +23,21 @@ import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.RepoForksActivity;
import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
@ -56,6 +63,9 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private LinearLayout archiveRepo;
private TextView repoBranch;
private TextView htmlUrl;
private ReposViewHolder(View itemView) {
@ -71,6 +81,9 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
repoBranch = itemView.findViewById(R.id.repoBranch);
htmlUrl = itemView.findViewById(R.id.htmlUrl);
itemView.setOnClickListener(v -> {
@ -81,25 +94,46 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", repoFullName.getText().toString());
TinyDB tinyDb = new TinyDB(context);
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putString("repoType", repoType_.getText().toString());
//tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
tinyDb.putString("repoBranch", repoBranch.getText().toString());
String[] parts = repoFullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
String[] parts = repoFullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchInfo watch = new WatchInfo();
Call<WatchInfo> call;
call = RetrofitClient.getInstance(instanceUrl, context).getApiInterface().checkRepoWatchStatus(token, repoOwner, repoName);
call = RetrofitClient.getApiInterface(context).checkRepoWatchStatus(token, repoOwner, repoName);
call.enqueue(new Callback<WatchInfo>() {
@ -117,7 +151,7 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
if(response.code() != 404) {
Toasty.info(context, context.getString(R.string.genericApiStatusError));
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
@ -129,10 +163,11 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) {
tinyDb.putBoolean("repoWatch", false);
Toasty.info(context, context.getString(R.string.genericApiStatusError));
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
});
}
context.startActivity(intent);
@ -148,13 +183,26 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
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(fullName.getText());
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);
@ -182,6 +230,15 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
});
repoForksList.setOnClickListener(forks -> {
Intent intentW = new Intent(context, RepoForksActivity.class);
intentW.putExtra("repoFullNameForForks", fullName.getText());
context.startActivity(intentW);
dialog.dismiss();
});
});
}
@ -208,6 +265,8 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
UserRepositories currentItem = reposList.get(position);
holder.repoDescription.setVisibility(View.GONE);
holder.repoBranch.setText(currentItem.getDefault_branch());
holder.htmlUrl.setText(currentItem.getHtml_url());
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
@ -232,13 +291,13 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullname());
holder.fullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold);
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_public);
holder.repoPrivatePublic.setVisibility(View.GONE);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStars.setText(currentItem.getStars_count());
@ -249,6 +308,13 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
}
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
}
@Override
@ -277,7 +343,7 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
String filterPattern = constraint.toString().toLowerCase().trim();
for(UserRepositories item : reposListFull) {
if(item.getFullname().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
if(item.getFullName().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}

View File

@ -1,6 +1,8 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
@ -11,26 +13,31 @@ import android.widget.CheckBox;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.RepoForksActivity;
import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
@ -56,6 +63,9 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private LinearLayout archiveRepo;
private TextView repoBranch;
private TextView htmlUrl;
private OrgReposViewHolder(View itemView) {
super(itemView);
@ -70,6 +80,9 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
repoBranch = itemView.findViewById(R.id.repoBranch);
htmlUrl = itemView.findViewById(R.id.htmlUrl);
itemView.setOnClickListener(v -> {
@ -78,25 +91,44 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", fullName.getText().toString());
TinyDB tinyDb = new TinyDB(context);
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("repoFullName", fullName.getText().toString());
tinyDb.putString("repoType", repoType.getText().toString());
//tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
tinyDb.putString("repoBranch", repoBranch.getText().toString());
String[] parts = fullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
String[] parts = fullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchInfo watch = new WatchInfo();
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
Call<WatchInfo> call;
call = RetrofitClient.getInstance(instanceUrl, context).getApiInterface().checkRepoWatchStatus(token, repoOwner, repoName);
call = RetrofitClient.getApiInterface(context).checkRepoWatchStatus(token, repoOwner, repoName);
call.enqueue(new Callback<WatchInfo>() {
@ -114,7 +146,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
if(response.code() != 404) {
Toasty.info(context, context.getString(R.string.genericApiStatusError));
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
@ -126,10 +158,11 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) {
tinyDb.putBoolean("repoWatch", false);
Toasty.info(context, context.getString(R.string.genericApiStatusError));
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
});
}
context.startActivity(intent);
@ -145,13 +178,26 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
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(fullName.getText());
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);
@ -161,7 +207,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
});
repoStargazers.setOnClickListener(openInBrowser -> {
repoStargazers.setOnClickListener(stargazers -> {
Intent intent = new Intent(context, RepoStargazersActivity.class);
intent.putExtra("repoFullNameForStars", fullName.getText());
@ -170,7 +216,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
});
repoWatchers.setOnClickListener(openInBrowser -> {
repoWatchers.setOnClickListener(watchers -> {
Intent intentW = new Intent(context, RepoWatchersActivity.class);
intentW.putExtra("repoFullNameForWatchers", fullName.getText());
@ -179,6 +225,15 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
});
repoForksList.setOnClickListener(forks -> {
Intent intentW = new Intent(context, RepoForksActivity.class);
intentW.putExtra("repoFullNameForForks", fullName.getText());
context.startActivity(intentW);
dialog.dismiss();
});
});
}
@ -203,6 +258,8 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
UserRepositories currentItem = reposList.get(position);
holder.repoDescription.setVisibility(View.GONE);
holder.repoBranch.setText(currentItem.getDefault_branch());
holder.htmlUrl.setText(currentItem.getHtml_url());
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
@ -234,13 +291,13 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullname());
holder.fullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold);
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_public);
holder.repoPrivatePublic.setVisibility(View.GONE);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStars.setText(currentItem.getStars_count());
@ -252,6 +309,13 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
}
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
}
@Override
@ -275,7 +339,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
String filterPattern = constraint.toString().toLowerCase().trim();
for (UserRepositories item : reposListFull) {
if (item.getFullname().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
if (item.getFullName().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}

View File

@ -0,0 +1,172 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Issues;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
/**
* Author M M Arif
*/
public class SearchIssuesAdapter extends RecyclerView.Adapter<SearchIssuesAdapter.SearchViewHolder> {
private List<Issues> searchedList;
private Context mCtx;
private TinyDB tinyDb;
public SearchIssuesAdapter(List<Issues> dataList, Context mCtx) {
this.mCtx = mCtx;
this.searchedList = dataList;
this.tinyDb = TinyDB.getInstance(mCtx);
}
class SearchViewHolder extends RecyclerView.ViewHolder {
private TextView issueNumber;
private ImageView issueAssigneeAvatar;
private TextView issueTitle;
private TextView issueCreatedTime;
private TextView issueCommentsCount;
private TextView repoFullName;
private SearchViewHolder(View itemView) {
super(itemView);
issueNumber = itemView.findViewById(R.id.issueNumber);
issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
issueTitle = itemView.findViewById(R.id.issueTitle);
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
repoFullName = itemView.findViewById(R.id.repoFullName);
issueTitle.setOnClickListener(v -> {
Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText());
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "Issue");
tinyDb.putString("repoFullName", repoFullName.getText().toString());
String[] parts = repoFullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
context.startActivity(intent);
});
}
}
@NonNull
@Override
public SearchIssuesAdapter.SearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_issues, parent, false);
return new SearchIssuesAdapter.SearchViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull final SearchIssuesAdapter.SearchViewHolder holder, int position) {
Issues currentItem = searchedList.get(position);
String locale = tinyDb.getString("locale");
String timeFormat = tinyDb.getString("dateFormat");
if(!currentItem.getUser().getFull_name().equals("")) {
holder.issueAssigneeAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCreator) + currentItem.getUser().getFull_name(), mCtx));
}
else {
holder.issueAssigneeAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCreator) + currentItem.getUser().getLogin(), mCtx));
}
PicassoService
.getInstance(mCtx).get().load(currentItem.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.issueAssigneeAvatar);
String issueNumber_ = "<font color='" + mCtx.getResources().getColor(R.color.lightGray) + "'>" + currentItem.getRepository().getFull_name() + mCtx.getResources().getString(R.string.hash) + currentItem.getNumber() + "</font>";
holder.issueTitle.setText(Html.fromHtml(issueNumber_ + " " + currentItem.getTitle()));
holder.issueNumber.setText(String.valueOf(currentItem.getNumber()));
holder.issueCommentsCount.setText(String.valueOf(currentItem.getComments()));
holder.repoFullName.setText(currentItem.getRepository().getFull_name());
switch(timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(currentItem.getCreated_at());
holder.issueCreatedTime.setText(createdTime);
holder.issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getCreated_at()), mCtx));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + mCtx.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(currentItem.getCreated_at());
holder.issueCreatedTime.setText(createdTime);
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + mCtx.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(currentItem.getCreated_at());
holder.issueCreatedTime.setText(createdTime);
break;
}
}
}
@Override
public int getItemCount() {
return searchedList.size();
}
public void notifyDataChanged() {
notifyDataSetChanged();
}
}

View File

@ -1,6 +1,8 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
@ -11,26 +13,31 @@ import android.widget.CheckBox;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.RepoForksActivity;
import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
@ -56,6 +63,9 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
private TextView repoForks;
private TextView repoOpenIssuesCount;
private TextView repoType;
private LinearLayout archiveRepo;
private TextView repoBranch;
private TextView htmlUrl;
private StarredReposViewHolder(View itemView) {
super(itemView);
@ -70,6 +80,9 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
repoBranch = itemView.findViewById(R.id.repoBranch);
htmlUrl = itemView.findViewById(R.id.htmlUrl);
itemView.setOnClickListener(v -> {
@ -78,25 +91,46 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
Intent intent = new Intent(context, RepoDetailActivity.class);
intent.putExtra("repoFullName", fullName.getText().toString());
TinyDB tinyDb = new TinyDB(context);
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("repoFullName", fullName.getText().toString());
tinyDb.putString("repoType", repoType.getText().toString());
//tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
tinyDb.putString("repoBranch", repoBranch.getText().toString());
String[] parts = fullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(context);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
String[] parts = fullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchInfo watch = new WatchInfo();
Call<WatchInfo> call;
call = RetrofitClient.getInstance(instanceUrl, context).getApiInterface().checkRepoWatchStatus(token, repoOwner, repoName);
call = RetrofitClient.getApiInterface(context).checkRepoWatchStatus(token, repoOwner, repoName);
call.enqueue(new Callback<WatchInfo>() {
@ -130,6 +164,7 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
}
});
}
context.startActivity(intent);
@ -146,13 +181,26 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
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(fullName.getText());
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);
@ -180,6 +228,15 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
});
repoForksList.setOnClickListener(forks -> {
Intent intentW = new Intent(context, RepoForksActivity.class);
intentW.putExtra("repoFullNameForForks", fullName.getText());
context.startActivity(intentW);
dialog.dismiss();
});
});
}
@ -204,6 +261,8 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
UserRepositories currentItem = reposList.get(position);
holder.repoDescription.setVisibility(View.GONE);
holder.repoBranch.setText(currentItem.getDefault_branch());
holder.htmlUrl.setText(currentItem.getHtml_url());
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
@ -235,13 +294,13 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullname());
holder.fullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold);
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_public);
holder.repoPrivatePublic.setVisibility(View.GONE);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStars.setText(currentItem.getStars_count());
@ -252,6 +311,13 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
}
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
}
@Override
@ -275,7 +341,7 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
String filterPattern = constraint.toString().toLowerCase().trim();
for (UserRepositories item : reposListFull) {
if (item.getFullname().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
if (item.getFullName().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}

View File

@ -11,10 +11,9 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.FontsOverride;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
/**
@ -83,7 +82,7 @@ public class TeamMembersByOrgAdapter extends BaseAdapter {
UserInfo currentItem = teamMembersList.get(position);
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.memberAvatar);
final TinyDB tinyDb = new TinyDB(mCtx);
final TinyDB tinyDb = TinyDB.getInstance(mCtx);
Typeface myTypeface;
switch(tinyDb.getInt("customFontId", -1)) {
@ -111,12 +110,5 @@ public class TeamMembersByOrgAdapter extends BaseAdapter {
viewHolder.memberName.setTypeface(myTypeface);
}
if(tinyDb.getInt("themeId") == 1) { //light
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.lightThemeTextColor));
}
else { // dark
viewHolder.memberName.setTextColor(mCtx.getResources().getColor(R.color.white));
}
}
}

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