Compare commits

...

33 Commits

Author SHA1 Message Date
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
185 changed files with 4240 additions and 3115 deletions

View File

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

View File

@ -36,6 +36,7 @@
<option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" /> <option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" /> <option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_SYNCHRONIZED_PARENTHESES" value="false" /> <option name="SPACE_BEFORE_SYNCHRONIZED_PARENTHESES" value="false" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="3" /> <option name="IF_BRACE_FORCE" value="3" />
<option name="WRAP_ON_TYPING" value="1" /> <option name="WRAP_ON_TYPING" value="1" />
<indentOptions> <indentOptions>
@ -156,4 +157,4 @@
</arrangement> </arrangement>
</codeStyleSettings> </codeStyleSettings>
</code_scheme> </code_scheme>
</component> </component>

View File

@ -1,2 +1,2 @@
# Changelog # 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

@ -10,7 +10,7 @@ Please ask if you are not sure about the scope of work to be submitted to avoid
**Code Standards** **Code Standards**
Please follow the code standards, this will help other developers to understand your code too. Please follow the code standards, this will help other developers to understand your code too.
It also helps maintaining the code afterwards. 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** **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. 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.

View File

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

View File

@ -1,4 +1,4 @@
[![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) [![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) [<img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg" height="40"/>](https://liberapay.com/mmarif/donate)
@ -18,7 +18,7 @@ Download latest build from master: [https://cloud.swatian.com/s/Cq592xGEfnsGAAW]
## Note about Gitea version ## Note about Gitea version
Please make sure that you are on latest stable release or later for better app experience. Please make sure that you are on latest stable release or later for better app experience.
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 ## Build from source
Option 1 - Download the source code, open it in Android Studio and build it there. Option 1 - Download the source code, open it in Android Studio and build it there.
@ -32,41 +32,41 @@ Option 2 - Open terminal(Linux) and cd to the project dir. Run `./gradlew build`
- Issues list - Issues list
- Pull requests - Pull requests
- Merge pull request - Merge pull request
- [MANY MORE](https://gitea.com/gitnex/GitNex/wiki/Features) - [MANY MORE](https://codeberg.org/gitnex/GitNex/wiki/Features)
## Contributing ## Contributing
[CONTRIBUTING](https://gitea.com/gitnex/GitNex/src/branch/master/CONTRIBUTING.md) [CONTRIBUTING](https://codeberg.org/gitnex/GitNex/src/branch/master/CONTRIBUTING.md)
## Translation ## Translation
Help us translate GitNex to your native language. 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** **Link: https://crowdin.com/project/GitNex**
## Screenshots: ## 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
[Faq](https://gitea.com/gitnex/GitNex/wiki/FAQ) [Faq](https://codeberg.org/gitnex/GitNex/wiki/FAQ)
## Links ## Links
[Website](https://gitnex.com) [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) [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
Thanks to all the open source libraries, contributors and donators. Thanks to all the open source libraries, contributors and donators.
Open source libraries #### Open source libraries
- Retrofit - Retrofit
- Gson - Gson
- Okhttp - Okhttp
@ -87,5 +87,7 @@ Open source libraries
- Droidsonroids.gif/android-gif-drawable - Droidsonroids.gif/android-gif-drawable
- Barteksc/AndroidPdfViewer - Barteksc/AndroidPdfViewer
- Ge0rg/MemorizingTrustManager - Ge0rg/MemorizingTrustManager
- Dimezis/BlurView
- mikaelhg/urlbuilder
[Follow me on Fediverse - mastodon.social/@mmarif](https://mastodon.social/@mmarif) [Follow me on Fediverse - mastodon.social/@mmarif](https://mastodon.social/@mmarif)

View File

@ -6,8 +6,8 @@ android {
applicationId "org.mian.gitnex" applicationId "org.mian.gitnex"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
versionCode 295 versionCode 297
versionName "3.0.0-rc1" versionName "3.0.0-rc3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
viewBinding { viewBinding {
@ -36,27 +36,28 @@ configurations {
} }
dependencies { dependencies {
def lifecycle_version = "2.2.0" def lifecycle_version = "2.3.0-alpha05"
def markwon_version = '4.3.1' def markwon_version = '4.4.0'
def acra = "5.5.0" def acra = "5.5.0"
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "androidx.appcompat:appcompat:1.2.0-rc01" implementation "androidx.appcompat:appcompat:1.3.0-alpha01"
implementation "com.google.android.material:material:1.2.0-beta01" implementation "com.google.android.material:material:1.3.0-alpha01"
implementation "androidx.constraintlayout:constraintlayout:1.1.3" implementation "androidx.constraintlayout:constraintlayout:1.1.3"
implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
testImplementation "junit:junit:4.13" testImplementation "junit:junit:4.13"
androidTestImplementation "androidx.test:runner:1.2.0" androidTestImplementation "androidx.test:runner:1.2.0"
androidTestImplementation "androidx.test.espresso:espresso-core:3.2.0" androidTestImplementation "androidx.test.espresso:espresso-core:3.2.0"
implementation "com.github.vihtarb:tooltip:0.2.0" implementation "com.github.vihtarb:tooltip:0.2.0"
implementation 'com.squareup.okhttp3:okhttp:4.7.0' implementation 'com.squareup.okhttp3:okhttp:4.7.2'
implementation "com.google.code.gson:gson:2.8.6" implementation "com.google.code.gson:gson:2.8.6"
implementation "com.squareup.picasso:picasso:2.71828" implementation "com.squareup.picasso:picasso:2.71828"
implementation "com.amulyakhare:com.amulyakhare.textdrawable:1.0.1" implementation "com.amulyakhare:com.amulyakhare.textdrawable:1.0.1"
implementation 'com.squareup.retrofit2:retrofit:2.8.1' implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.8.1' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.8.1' implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.7.0' implementation 'com.squareup.okhttp3:logging-interceptor:4.7.2'
implementation 'org.ocpsoft.prettytime:prettytime:4.0.5.Final' implementation 'org.ocpsoft.prettytime:prettytime:4.0.5.Final'
implementation "com.vdurmont:emoji-java:5.1.1" implementation "com.vdurmont:emoji-java:5.1.1"
implementation "com.pes.materialcolorpicker:library:1.2.5" implementation "com.pes.materialcolorpicker:library:1.2.5"
@ -77,8 +78,6 @@ dependencies {
implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.19" implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.19"
implementation "com.hendraanggrian.appcompat:socialview:0.2" implementation "com.hendraanggrian.appcompat:socialview:0.2"
implementation "com.hendraanggrian.appcompat:socialview-commons:0.2" implementation "com.hendraanggrian.appcompat:socialview-commons:0.2"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
implementation "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9" implementation "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9"
implementation "commons-io:commons-io:20030203.000550" implementation "commons-io:commons-io:20030203.000550"
implementation "com.github.chrisbanes:PhotoView:2.3.0" implementation "com.github.chrisbanes:PhotoView:2.3.0"
@ -86,5 +85,7 @@ dependencies {
implementation "ch.acra:acra-mail:$acra" implementation "ch.acra:acra-mail:$acra"
implementation "ch.acra:acra-limiter:$acra" implementation "ch.acra:acra-limiter:$acra"
implementation "ch.acra:acra-notification:$acra" implementation "ch.acra:acra-notification:$acra"
implementation "com.eightbitlab:blurview:1.6.3"
implementation "io.mikael:urlbuilder:2.0.9"
} }

View File

@ -203,7 +203,7 @@ public class IssueActions {
} }
else { else {
Toasty.info(ctx, ctx.getString(R.string.subscribtionError)); Toasty.info(ctx, ctx.getString(R.string.subscriptionError));
} }
@ -263,7 +263,7 @@ public class IssueActions {
} }
else { else {
Toasty.info(ctx, ctx.getString(R.string.unsubscribtionError)); Toasty.info(ctx, ctx.getString(R.string.unsubscriptionError));
} }
@ -272,7 +272,7 @@ public class IssueActions {
@Override @Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Toasty.info(ctx, ctx.getString(R.string.unsubscribtionError)); Toasty.info(ctx, ctx.getString(R.string.unsubscriptionError));
} }
}); });
} }

View File

@ -96,7 +96,7 @@ public class AddNewTeamMemberActivity extends BaseActivity {
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { 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)); adapter = new UserSearchForTeamMemberAdapter(dataList, ctx, Integer.parseInt(teamId));
loadUserSearchList(instanceUrl, instanceToken, addNewTeamMember.getText().toString(), loginUid, teamId); loadUserSearchList(instanceUrl, instanceToken, addNewTeamMember.getText().toString(), loginUid, teamId);

View File

@ -1,13 +1,5 @@
package org.mian.gitnex.activities; 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.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
@ -19,16 +11,20 @@ import android.view.View;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; 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.R;
import org.mian.gitnex.adapters.AdminGetUsersAdapter; import org.mian.gitnex.adapters.AdminGetUsersAdapter;
import org.mian.gitnex.fragments.BottomSheetAdminUsersFragment; import org.mian.gitnex.fragments.BottomSheetAdminUsersFragment;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil; import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB; import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.AdminGetUsersViewModel; import org.mian.gitnex.viewmodels.AdminGetUsersViewModel;
import java.util.List;
import java.util.Objects;
/** /**
* Author M M Arif * Author M M Arif
@ -79,18 +75,12 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
DividerItemDecoration.VERTICAL); DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration); mRecyclerView.addItemDecoration(dividerItemDecoration);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
@Override
public void onRefresh() { swipeRefresh.setRefreshing(false);
new Handler().postDelayed(new Runnable() { AdminGetUsersViewModel.loadUsersList(ctx, instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken));
@Override
public void run() { }, 500));
swipeRefresh.setRefreshing(false);
AdminGetUsersViewModel.loadUsersList(ctx, instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken));
}
}, 500);
}
});
fetchDataAsync(ctx, instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken)); fetchDataAsync(ctx, instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken));
@ -98,25 +88,24 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
private void fetchDataAsync(Context ctx, String instanceUrl, String instanceToken) { private void fetchDataAsync(Context ctx, String instanceUrl, 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>>() { usersModel.getUsersList(ctx, instanceUrl, instanceToken).observe(this, usersListMain -> {
@Override
public void onChanged(@Nullable List<UserInfo> usersListMain) { adapter = new AdminGetUsersAdapter(ctx, usersListMain);
adapter = new AdminGetUsersAdapter(ctx, usersListMain); if(adapter.getItemCount() > 0) {
if(adapter.getItemCount() > 0) { mRecyclerView.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.VISIBLE); mRecyclerView.setAdapter(adapter);
mRecyclerView.setAdapter(adapter); noDataUsers.setVisibility(View.GONE);
noDataUsers.setVisibility(View.GONE); searchFilter = true;
searchFilter = true;
}
else {
//adapter.notifyDataSetChanged();
//mRecyclerView.setAdapter(adapter);
mRecyclerView.setVisibility(View.GONE);
noDataUsers.setVisibility(View.VISIBLE);
}
} }
else {
//adapter.notifyDataSetChanged();
//mRecyclerView.setAdapter(adapter);
mRecyclerView.setVisibility(View.GONE);
noDataUsers.setVisibility(View.VISIBLE);
}
}); });
} }
@ -127,37 +116,36 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
final MenuInflater inflater = getMenuInflater(); final MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.generic_nav_dotted_menu, menu); inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
new Handler().postDelayed(new Runnable() { new Handler().postDelayed(() -> {
@Override
public void run() {
if(searchFilter) {
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); inflater.inflate(R.menu.search_menu, menu);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
if(!connToInternet) { MenuItem searchItem = menu.findItem(R.id.action_search);
return; 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); }, 500);
return true; return true;
@ -194,12 +182,7 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
} }
private void initCloseListener() { private void initCloseListener() {
onClickListener = new View.OnClickListener() { onClickListener = view -> finish();
@Override
public void onClick(View view) {
finish();
}
};
} }
} }

View File

@ -103,6 +103,11 @@ public abstract class BaseActivity extends AppCompatActivity {
tinyDb.putString("cacheSizeImagesStr", getResources().getString(R.string.cacheSizeImagesSelectionSelectedText)); tinyDb.putString("cacheSizeImagesStr", getResources().getString(R.string.cacheSizeImagesSelectionSelectedText));
} }
if(!tinyDb.getString("instanceUrlWithProtocol").endsWith("/")) {
tinyDb.putString("instanceUrlWithProtocol", tinyDb.getString("instanceUrlWithProtocol") + "/");
}
if (tinyDb.getBoolean("crashReportingEnabled")) { if (tinyDb.getBoolean("crashReportingEnabled")) {
CoreConfigurationBuilder ACRABuilder = new CoreConfigurationBuilder(this); CoreConfigurationBuilder ACRABuilder = new CoreConfigurationBuilder(this);

View File

@ -23,7 +23,6 @@ import org.mian.gitnex.adapters.CommitsAdapter;
import org.mian.gitnex.clients.AppApiService; import org.mian.gitnex.clients.AppApiService;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables; import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.interfaces.ApiInterface; import org.mian.gitnex.interfaces.ApiInterface;
import org.mian.gitnex.models.Commits; import org.mian.gitnex.models.Commits;
@ -102,7 +101,7 @@ public class CommitsActivity extends BaseActivity {
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> { swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setRefreshing(false); swipeRefresh.setRefreshing(false);
loadInitial(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName); loadInitial(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName, resultLimit);
adapter.notifyDataChanged(); adapter.notifyDataChanged();
}, 200)); }, 200));
@ -113,7 +112,7 @@ public class CommitsActivity extends BaseActivity {
if(commitsList.size() == resultLimit || pageSize == resultLimit) { if(commitsList.size() == resultLimit || pageSize == resultLimit) {
int page = (commitsList.size() + resultLimit) / resultLimit; int page = (commitsList.size() + resultLimit) / resultLimit;
loadMore(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, page, branchName); loadMore(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, page, branchName, resultLimit);
} }
@ -124,13 +123,13 @@ public class CommitsActivity extends BaseActivity {
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
api = AppApiService.createService(ApiInterface.class, instanceUrl, ctx); api = AppApiService.createService(ApiInterface.class, instanceUrl, ctx);
loadInitial(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName); loadInitial(Authorization.returnAuthentication(ctx, loginUid, instanceToken), 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 = api.getRepositoryCommits(token, repoOwner, repoName, 1, branchName, resultLimit);
call.enqueue(new Callback<List<Commits>>() { call.enqueue(new Callback<List<Commits>>() {
@ -175,13 +174,13 @@ public class CommitsActivity extends BaseActivity {
} }
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 //add loading progress view
commitsList.add(new Commits("load")); commitsList.add(new Commits("load"));
adapter.notifyItemInserted((commitsList.size() - 1)); adapter.notifyItemInserted((commitsList.size() - 1));
Call<List<Commits>> call = api.getRepositoryCommits(token, repoOwner, repoName, page, branchName); Call<List<Commits>> call = api.getRepositoryCommits(token, repoOwner, repoName, page, branchName, resultLimit);
call.enqueue(new Callback<List<Commits>>() { call.enqueue(new Callback<List<Commits>>() {
@ -204,7 +203,6 @@ public class CommitsActivity extends BaseActivity {
} }
else { else {
Toasty.info(ctx, getString(R.string.noMoreData));
adapter.setMoreDataAvailable(false); adapter.setMoreDataAvailable(false);
} }

View File

@ -61,7 +61,7 @@ public class CreateFileActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -146,7 +146,7 @@ public class CreateFileActivity extends BaseActivity {
private void processNewFile() { private void processNewFile() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");

View File

@ -82,7 +82,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -153,7 +153,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private void processNewIssue() { private void processNewIssue() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid"); final String loginUid = tinyDb.getString("loginUid");

View File

@ -73,7 +73,7 @@ public class CreateLabelActivity extends BaseActivity {
} }
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = findViewById(R.id.close);
colorPicker = findViewById(R.id.colorPicker); colorPicker = findViewById(R.id.colorPicker);
@ -154,7 +154,7 @@ public class CreateLabelActivity extends BaseActivity {
private void processUpdateLabel() { private void processUpdateLabel() {
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(appCtx);
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
String repoFullName = tinyDb.getString("repoFullName"); String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
@ -202,7 +202,7 @@ public class CreateLabelActivity extends BaseActivity {
private void processCreateLabel() { private void processCreateLabel() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
String repoFullName = tinyDb.getString("repoFullName"); String repoFullName = tinyDb.getString("repoFullName");
@ -446,4 +446,4 @@ public class CreateLabelActivity extends BaseActivity {
} }
} }

View File

@ -50,7 +50,7 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -92,7 +92,7 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
private void processNewMilestone() { private void processNewMilestone() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
String repoFullName = tinyDb.getString("repoFullName"); String repoFullName = tinyDb.getString("repoFullName");

View File

@ -48,7 +48,7 @@ public class CreateNewUserActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -80,7 +80,7 @@ public class CreateNewUserActivity extends BaseActivity {
private void processCreateNewUser() { private void processCreateNewUser() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");

View File

@ -47,7 +47,7 @@ public class CreateOrganizationActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -97,7 +97,7 @@ public class CreateOrganizationActivity extends BaseActivity {
private void processNewOrganization() { private void processNewOrganization() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");

View File

@ -60,7 +60,7 @@ public class CreateReleaseActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -125,7 +125,7 @@ public class CreateReleaseActivity extends BaseActivity {
private void processNewRelease() { private void processNewRelease() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");

View File

@ -64,7 +64,7 @@ public class CreateRepoActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(ctx); boolean connToInternet = AppUtil.hasNetworkConnection(ctx);
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
@ -124,7 +124,7 @@ public class CreateRepoActivity extends BaseActivity {
private void processNewRepo() { private void processNewRepo() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");

View File

@ -78,7 +78,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -256,7 +256,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final String orgName = tinyDb.getString("orgName");; final String orgName = tinyDb.getString("orgName");;
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newTeamName = teamName.getText().toString(); String newTeamName = teamName.getText().toString();
String newTeamDesc = teamDesc.getText().toString(); String newTeamDesc = teamDesc.getText().toString();
String newTeamPermission = teamPermission.getText().toString().toLowerCase(); String newTeamPermission = teamPermission.getText().toString().toLowerCase();

View File

@ -196,7 +196,7 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
private void processEditIssue() { private void processEditIssue() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid"); final String loginUid = tinyDb.getString("loginUid");

View File

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

View File

@ -12,6 +12,7 @@ import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -22,7 +23,6 @@ import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import com.google.android.material.navigation.NavigationView; import com.google.android.material.navigation.NavigationView;
import com.squareup.picasso.NetworkPolicy;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
@ -38,6 +38,7 @@ import org.mian.gitnex.fragments.StarredRepositoriesFragment;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.ChangeLog; import org.mian.gitnex.helpers.ChangeLog;
import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.GiteaVersion; import org.mian.gitnex.models.GiteaVersion;
@ -45,6 +46,8 @@ import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil; import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB; import org.mian.gitnex.util.TinyDB;
import java.util.Objects; import java.util.Objects;
import eightbitlab.com.blurview.BlurView;
import eightbitlab.com.blurview.RenderScriptBlur;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -55,9 +58,12 @@ import retrofit2.Callback;
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener { public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener {
private DrawerLayout drawer; private DrawerLayout drawer;
private BlurView blurView;
private TextView userFullName; private TextView userFullName;
private TextView userEmail; private TextView userEmail;
private ImageView userAvatar; private ImageView userAvatar;
private ImageView userAvatarBackground;
private ViewGroup navHeaderFrame;
private TextView toolbarTitle; private TextView toolbarTitle;
final Context ctx = this; final Context ctx = this;
private Context appCtx; private Context appCtx;
@ -100,7 +106,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
tinyDb.putInt("homeScreenId", 0); 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); logout(this, ctx);
@ -131,6 +137,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
FragmentManager fm = getSupportFragmentManager(); FragmentManager fm = getSupportFragmentManager();
Fragment fragmentById = fm.findFragmentById(R.id.fragment_container); Fragment fragmentById = fm.findFragmentById(R.id.fragment_container);
if(fragmentById instanceof SettingsFragment) { if(fragmentById instanceof SettingsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings)); toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
} }
@ -163,15 +170,10 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
toggle.getDrawerArrowDrawable().setColor(getResources().getColor(R.color.darkGreen)); toggle.getDrawerArrowDrawable().setColor(getResources().getColor(R.color.darkGreen));
drawer.addDrawerListener(toggle); drawer.addDrawerListener(toggle);
drawer.addDrawerListener(new DrawerLayout.DrawerListener() { drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
}
@Override @Override
public void onDrawerOpened(@NonNull View drawerView) { public void onDrawerOpened(@NonNull View drawerView) {
@ -184,78 +186,119 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
String userFullNameNav = tinyDb.getString("userFullname"); String userFullNameNav = tinyDb.getString("userFullname");
String userAvatarNav = tinyDb.getString("userAvatar"); String userAvatarNav = tinyDb.getString("userAvatar");
blurView = hView.findViewById(R.id.blurView);
userEmail = hView.findViewById(R.id.userEmail); userEmail = hView.findViewById(R.id.userEmail);
userFullName = hView.findViewById(R.id.userFullname);
userAvatar = hView.findViewById(R.id.userAvatar);
userAvatarBackground = hView.findViewById(R.id.userAvatarBackground);
navHeaderFrame = hView.findViewById(R.id.navHeaderFrame);
userEmail.setTypeface(myTypeface);
userFullName.setTypeface(myTypeface);
navigationView.getMenu().findItem(R.id.nav_administration).setVisible(tinyDb.getBoolean("userIsAdmin"));
if(!userEmailNav.equals("")) { if(!userEmailNav.equals("")) {
userEmail.setText(userEmailNav); userEmail.setText(userEmailNav);
userEmail.setTypeface(myTypeface);
} }
userFullName = hView.findViewById(R.id.userFullname);
if(!userFullNameNav.equals("")) { if(!userFullNameNav.equals("")) {
userFullName.setText(userFullNameNav); userFullName.setText(userFullNameNav);
userFullName.setTypeface(myTypeface);
} }
userAvatar = hView.findViewById(R.id.userAvatar);
if(!userAvatarNav.equals("")) { 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);
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(new View.OnClickListener() { userAvatar.setOnClickListener(v -> {
public void onClick(View v) { toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit(); drawer.closeDrawers();
drawer.closeDrawers();
}
}); });
} }
@Override @Override
public void onDrawerClosed(@NonNull View drawerView) { public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {}
// Called when a drawer has settled in a completely closed state.
}
@Override @Override
public void onDrawerStateChanged(int newState) { public void onDrawerClosed(@NonNull View drawerView) {}
// Called when the drawer motion state changes. The new state will be one of STATE_IDLE, STATE_DRAGGING or STATE_SETTLING.
} @Override
public void onDrawerStateChanged(int newState) {}
}); });
toggle.syncState(); toggle.syncState();
if(savedInstanceState == null) { if(savedInstanceState == null) {
if(tinyDb.getInt("homeScreenId") == 0) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos)); switch(tinyDb.getInt("homeScreenId")) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home); case 1:
} toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
else if(tinyDb.getInt("homeScreenId") == 1) { getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos)); navigationView.setCheckedItem(R.id.nav_starred_repos);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit(); break;
navigationView.setCheckedItem(R.id.nav_starred_repos);
} case 2:
else if(tinyDb.getInt("homeScreenId") == 2) { toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations)); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit(); navigationView.setCheckedItem(R.id.nav_organizations);
navigationView.setCheckedItem(R.id.nav_organizations); break;
}
else if(tinyDb.getInt("homeScreenId") == 3) { case 3:
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories)); toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories); navigationView.setCheckedItem(R.id.nav_repositories);
} break;
else if(tinyDb.getInt("homeScreenId") == 4) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile)); case 4:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit(); toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
navigationView.setCheckedItem(R.id.nav_profile); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
} navigationView.setCheckedItem(R.id.nav_profile);
else { break;
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit(); default:
navigationView.setCheckedItem(R.id.nav_home); 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(!connToInternet) {
@ -269,7 +312,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
} }
else { else {
displayUserInfo(instanceUrl, instanceToken, loginUid); loadUserInfo(instanceUrl, instanceToken, loginUid);
giteaVersion(instanceUrl); giteaVersion(instanceUrl);
tinyDb.putBoolean("noConnection", false); tinyDb.putBoolean("noConnection", false);
@ -314,46 +357,56 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
switch(menuItem.getItemId()) { switch(menuItem.getItemId()) {
case R.id.nav_home: case R.id.nav_home:
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos)); toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
break; break;
case R.id.nav_organizations: case R.id.nav_organizations:
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations)); toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
break; break;
case R.id.nav_profile: case R.id.nav_profile:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile)); toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
break; break;
case R.id.nav_repositories: case R.id.nav_repositories:
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories)); toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
break; break;
case R.id.nav_settings: case R.id.nav_settings:
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings)); toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new SettingsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new SettingsFragment()).commit();
break; break;
case R.id.nav_logout: case R.id.nav_logout:
logout(this, ctx); logout(this, ctx);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
break; break;
case R.id.nav_about: case R.id.nav_about:
toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout)); toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AboutFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AboutFragment()).commit();
break; break;
case R.id.nav_rate_app: case R.id.nav_rate_app:
rateThisApp(); rateThisApp();
break; break;
case R.id.nav_starred_repos: case R.id.nav_starred_repos:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos)); toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
break; break;
case R.id.nav_explore: case R.id.nav_explore:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore)); toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreRepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreRepositoriesFragment()).commit();
break; break;
case R.id.nav_administration: case R.id.nav_administration:
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration)); toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AdministrationFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AdministrationFragment()).commit();
@ -422,15 +475,12 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
} }
private void displayUserInfo(String instanceUrl, String token, String loginUid) { private void loadUserInfo(String instanceUrl, String token, String loginUid) {
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(appCtx);
Call<UserInfo> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserInfo(Authorization.returnAuthentication(ctx, loginUid, token)); 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.enqueue(new Callback<UserInfo>() { call.enqueue(new Callback<UserInfo>() {
@Override @Override
@ -443,12 +493,14 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
if(response.code() == 200) { if(response.code() == 200) {
assert userDetails != null; assert userDetails != null;
if(userDetails.getIs_admin() != null) { if(userDetails.getIs_admin() != null) {
tinyDb.putBoolean("userIsAdmin", userDetails.getIs_admin()); tinyDb.putBoolean("userIsAdmin", userDetails.getIs_admin());
navigationView.getMenu().findItem(R.id.nav_administration).setVisible(userDetails.getIs_admin());
} }
tinyDb.putString("userLogin", userDetails.getLogin()); tinyDb.putString("userLogin", userDetails.getLogin());
tinyDb.putInt("userId", userDetails.getId()); tinyDb.putInt("userId", userDetails.getId());
if(!userDetails.getFullname().equals("")) { if(!userDetails.getFullname().equals("")) {
tinyDb.putString("userFullname", userDetails.getFullname()); tinyDb.putString("userFullname", userDetails.getFullname());
} }
@ -458,51 +510,14 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
tinyDb.putString("userEmail", userDetails.getEmail()); tinyDb.putString("userEmail", userDetails.getEmail());
tinyDb.putString("userAvatar", userDetails.getAvatar()); tinyDb.putString("userAvatar", userDetails.getAvatar());
if(userDetails.getLang() != null) { if(userDetails.getLang() != null) {
tinyDb.putString("userLang", userDetails.getLang()); tinyDb.putString("userLang", userDetails.getLang());
} }
else { else {
tinyDb.putString("userLang", "..."); 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);
}
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) { else if(response.code() == 401) {
@ -511,7 +526,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
} }
else { else {
String toastError = getResources().getString(R.string.genericApiStatusError) + String.valueOf(response.code()); String toastError = getResources().getString(R.string.genericApiStatusError) + response.code();
Toasty.info(ctx, toastError); Toasty.info(ctx, toastError);
} }

View File

@ -62,7 +62,7 @@ public class MergePullRequestActivity extends BaseActivity {
View view = viewBinding.getRoot(); View view = viewBinding.getRoot();
setContentView(view); setContentView(view);
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -217,7 +217,7 @@ public class MergePullRequestActivity extends BaseActivity {
String mergePRTitle = viewBinding.mergeTitle.getText().toString(); String mergePRTitle = viewBinding.mergeTitle.getText().toString();
boolean deleteBranch = viewBinding.deleteBranch.isChecked(); boolean deleteBranch = viewBinding.deleteBranch.isChecked();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
if(!connToInternet) { if(!connToInternet) {

View File

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

@ -49,7 +49,7 @@ public class ProfileEmailActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); appCtx = getApplicationContext();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@ -84,7 +84,7 @@ public class ProfileEmailActivity extends BaseActivity {
private void processAddNewEmail() { private void processAddNewEmail() {
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid"); final String loginUid = tinyDb.getString("loginUid");

View File

@ -58,13 +58,13 @@ public class ReplyToIssueActivity extends BaseActivity {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(appCtx);
addComment = findViewById(R.id.addComment); addComment = findViewById(R.id.addComment);
addComment.setShowSoftInputOnFocus(true); addComment.setShowSoftInputOnFocus(true);
defaultMentionAdapter = new MentionArrayAdapter<>(this); defaultMentionAdapter = new MentionArrayAdapter<>(ctx);
loadCollaboratorsList(); loadCollaboratorsList();
addComment.setMentionAdapter(defaultMentionAdapter); addComment.setMentionAdapter(defaultMentionAdapter);
@ -191,7 +191,7 @@ public class ReplyToIssueActivity extends BaseActivity {
private void processNewCommentReply() { private void processNewCommentReply() {
String newReplyDT = addComment.getText().toString(); String newReplyDT = addComment.getText().toString();
boolean connToInternet = AppUtil.haveNetworkConnection(appCtx); boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
if(!connToInternet) { if(!connToInternet) {

View File

@ -42,7 +42,6 @@ import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.UserRepositories; import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo; import org.mian.gitnex.models.WatchInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB; import org.mian.gitnex.util.TinyDB;
import java.util.Objects; import java.util.Objects;
import retrofit2.Call; import retrofit2.Call;
@ -63,59 +62,19 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
private FragmentRefreshListenerPr fragmentRefreshListenerPr; private FragmentRefreshListenerPr fragmentRefreshListenerPr;
private FragmentRefreshListenerMilestone fragmentRefreshListenerMilestone; private FragmentRefreshListenerMilestone fragmentRefreshListenerMilestone;
final Context ctx = this; private final Context ctx = this;
private Context appCtx; private Context appCtx;
// issues interface private TinyDB tinyDB;
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener; private String instanceUrl;
} private String loginUid;
private String instanceToken;
public void setFragmentRefreshListener(FragmentRefreshListener fragmentRefreshListener) { private String repositoryOwner;
private String repositoryName;
this.fragmentRefreshListener = fragmentRefreshListener; private int tabsCount;
}
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);
}
@Override @Override
protected int getLayoutResourceId() { protected int getLayoutResourceId() {
@ -129,40 +88,32 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx); tinyDB = new TinyDB(appCtx);
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
String repoName1 = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl"); String[] repoNameParts = tinyDB.getString("repoFullName").split("/");
final String repoOwner = parts[0]; repositoryOwner = repoNameParts[0];
final String loginUid = tinyDb.getString("loginUid"); repositoryName = repoNameParts[1];
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);
Toolbar toolbar = findViewById(R.id.toolbar); Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title); TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
toolbarTitle.setText(repositoryName);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repoName1); Objects.requireNonNull(getSupportActionBar()).setTitle(repositoryName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); instanceUrl = tinyDB.getString("instanceUrl");
loginUid = tinyDB.getString("loginUid");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
ViewPager mViewPager = findViewById(R.id.container); tinyDB.putString("repoIssuesState", "open");
mViewPager.setAdapter(mSectionsPagerAdapter); tinyDB.putString("repoPrState", "open");
tinyDB.putString("milestoneState", "open");
TabLayout tabLayout = findViewById(R.id.tabs);
Typeface myTypeface; Typeface myTypeface;
switch(tinyDb.getInt("customFontId", -1)) { switch(tinyDB.getInt("customFontId", -1)) {
case 0: case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf"); myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
@ -179,34 +130,50 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
} }
toolbarTitle.setTypeface(myTypeface); toolbarTitle.setTypeface(myTypeface);
toolbarTitle.setText(repoName1);
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0); TabLayout tabLayout = findViewById(R.id.tabs);
int tabsCount = vg.getChildCount();
ViewGroup viewGroup = (ViewGroup) tabLayout.getChildAt(0);
tabsCount = viewGroup.getChildCount();
for(int j = 0; j < tabsCount; j++) { for(int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
ViewGroup vgTab = (ViewGroup) viewGroup.getChildAt(j);
int tabChildCount = vgTab.getChildCount(); int tabChildCount = vgTab.getChildCount();
for(int i = 0; i < tabChildCount; i++) { for(int i = 0; i < tabChildCount; i++) {
View tabViewChild = vgTab.getChildAt(i); View tabViewChild = vgTab.getChildAt(i);
if(tabViewChild instanceof TextView) { if(tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(myTypeface); ((TextView) tabViewChild).setTypeface(myTypeface);
} }
} }
} }
// only show Collaborators if you have permission to // Only show collaborators tab, if you have permission to
final View collaboratorTab = vg.getChildAt(8); View collaboratorTab = viewGroup.getChildAt(8);
if(tinyDb.getBoolean("isRepoAdmin")) {
if(tinyDB.getBoolean("isRepoAdmin") || new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
collaboratorTab.setVisibility(View.VISIBLE); collaboratorTab.setVisibility(View.VISIBLE);
} }
else { else {
tabsCount--;
collaboratorTab.setVisibility(View.GONE); collaboratorTab.setVisibility(View.GONE);
} }
ViewPager mViewPager = findViewById(R.id.container);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager)); 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); @SuppressLint("InflateParams") View tabHeader2 = LayoutInflater.from(this).inflate(R.layout.badge_issue, null);
textViewBadgeIssue = tabHeader2.findViewById(R.id.counterBadgeIssue); textViewBadgeIssue = tabHeader2.findViewById(R.id.counterBadgeIssue);
@ -221,41 +188,48 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
textViewBadgePull.setVisibility(View.GONE); textViewBadgePull.setVisibility(View.GONE);
textViewBadgeRelease.setVisibility(View.GONE); textViewBadgeRelease.setVisibility(View.GONE);
getRepoInfo(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName1); getRepoInfo(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
ColorStateList textColor = tabLayout.getTabTextColors(); ColorStateList textColor = tabLayout.getTabTextColors();
// issue count // Issue count
if(textViewBadgeIssue.getText() != "") { if(textViewBadgeIssue.getText() != "") {
TabLayout.Tab tabOpenIssues = tabLayout.getTabAt(2); TabLayout.Tab tabOpenIssues = tabLayout.getTabAt(2);
Objects.requireNonNull(tabLayout.getTabAt(2)).setCustomView(tabHeader2); 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); TextView openIssueTabView = Objects.requireNonNull(tabOpenIssues.getCustomView()).findViewById(R.id.counterBadgeIssueText);
openIssueTabView.setTextColor(textColor); openIssueTabView.setTextColor(textColor);
} }
// pull count // Pull request count
if(textViewBadgePull.getText() != "") { // only show if API returned a number if(textViewBadgePull.getText() != "") { // only show if API returned a number
Objects.requireNonNull(tabLayout.getTabAt(3)).setCustomView(tabHeader4); Objects.requireNonNull(tabLayout.getTabAt(3)).setCustomView(tabHeader4);
TabLayout.Tab tabOpenPulls = tabLayout.getTabAt(3); 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); TextView openPullTabView = Objects.requireNonNull(tabOpenPulls.getCustomView()).findViewById(R.id.counterBadgePullText);
openPullTabView.setTextColor(textColor); openPullTabView.setTextColor(textColor);
} }
// release count // Release count
if(new Version("1.11.4").less(tinyDb.getString("giteaVersion"))) { if(new Version("1.11.4").less(tinyDB.getString("giteaVersion"))) {
if(textViewBadgeRelease.getText() != "") { // only show if API returned a number if(textViewBadgeRelease.getText() != "") { // only show if API returned a number
Objects.requireNonNull(tabLayout.getTabAt(5)).setCustomView(tabHeader6); Objects.requireNonNull(tabLayout.getTabAt(5)).setCustomView(tabHeader6);
TabLayout.Tab tabOpenRelease = tabLayout.getTabAt(5); TabLayout.Tab tabOpenRelease = tabLayout.getTabAt(5);
assert tabOpenRelease != null; assert tabOpenRelease != null; // FIXME This should be cleaned up
TextView openReleaseTabView = Objects.requireNonNull(tabOpenRelease.getCustomView()).findViewById(R.id.counterBadgeReleaseText); TextView openReleaseTabView = Objects.requireNonNull(tabOpenRelease.getCustomView()).findViewById(R.id.counterBadgeReleaseText);
openReleaseTabView.setTextColor(textColor); openReleaseTabView.setTextColor(textColor);
} }
} }
} }
checkRepositoryStarStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName1); checkRepositoryStarStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
checkRepositoryWatchStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName1); checkRepositoryWatchStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
} }
@ -263,17 +237,10 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
public void onResume() { public void onResume() {
super.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")) { if(tinyDB.getBoolean("enableCounterIssueBadge")) {
getRepoInfo(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
getRepoInfo(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
} }
} }
@ -293,27 +260,34 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
int id = item.getItemId(); int id = item.getItemId();
switch(id) { switch(id) {
case android.R.id.home: case android.R.id.home:
finish(); finish();
return true; return true;
case R.id.repoMenu: case R.id.repoMenu:
BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment(); BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment();
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet"); bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
return true; return true;
case R.id.filter: case R.id.filter:
BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment(); BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment();
filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet"); filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet");
return true; return true;
case R.id.filterPr: case R.id.filterPr:
BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment(); BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment();
filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet"); filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet");
return true; return true;
case R.id.filterMilestone: case R.id.filterMilestone:
BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment(); BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment();
filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet"); filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet");
return true; return true;
default: default:
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
} }
@ -321,68 +295,81 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
@Override @Override
public void onButtonClicked(String text) { public void onButtonClicked(String text) {
TinyDB tinyDb = new TinyDB(appCtx);
switch(text) { switch(text) {
case "label": case "label":
startActivity(new Intent(RepoDetailActivity.this, CreateLabelActivity.class)); startActivity(new Intent(RepoDetailActivity.this, CreateLabelActivity.class));
break; break;
case "newIssue": case "newIssue":
startActivity(new Intent(RepoDetailActivity.this, CreateIssueActivity.class)); startActivity(new Intent(RepoDetailActivity.this, CreateIssueActivity.class));
break; break;
case "newMilestone": case "newMilestone":
startActivity(new Intent(RepoDetailActivity.this, CreateMilestoneActivity.class)); startActivity(new Intent(RepoDetailActivity.this, CreateMilestoneActivity.class));
break; break;
case "addCollaborator": case "addCollaborator":
startActivity(new Intent(RepoDetailActivity.this, AddCollaboratorToRepositoryActivity.class)); startActivity(new Intent(RepoDetailActivity.this, AddCollaboratorToRepositoryActivity.class));
break; break;
case "createRelease": case "createRelease":
startActivity(new Intent(RepoDetailActivity.this, CreateReleaseActivity.class)); startActivity(new Intent(RepoDetailActivity.this, CreateReleaseActivity.class));
break; break;
case "openWebRepo": 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); startActivity(i);
break; break;
case "shareRepo": case "shareRepo":
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain"); sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, tinyDb.getString("repoHtmlUrl")); sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, tinyDB.getString("repoHtmlUrl"));
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, tinyDb.getString("repoHtmlUrl")); sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, tinyDB.getString("repoHtmlUrl"));
startActivity(Intent.createChooser(sharingIntent, tinyDb.getString("repoHtmlUrl"))); startActivity(Intent.createChooser(sharingIntent, tinyDB.getString("repoHtmlUrl")));
break; break;
case "newFile": case "newFile":
startActivity(new Intent(RepoDetailActivity.this, CreateFileActivity.class)); startActivity(new Intent(RepoDetailActivity.this, CreateFileActivity.class));
break; break;
case "openIssues": case "openIssues":
if(getFragmentRefreshListener() != null) { if(getFragmentRefreshListener() != null) {
getFragmentRefreshListener().onRefresh("open"); getFragmentRefreshListener().onRefresh("open");
} }
break; break;
case "closedIssues": case "closedIssues":
if(getFragmentRefreshListener() != null) { if(getFragmentRefreshListener() != null) {
getFragmentRefreshListener().onRefresh("closed"); getFragmentRefreshListener().onRefresh("closed");
} }
break; break;
case "openPr": case "openPr":
if(getFragmentRefreshListenerPr() != null) { if(getFragmentRefreshListenerPr() != null) {
getFragmentRefreshListenerPr().onRefresh("open"); getFragmentRefreshListenerPr().onRefresh("open");
} }
break; break;
case "closedPr": case "closedPr":
if(getFragmentRefreshListenerPr() != null) { if(getFragmentRefreshListenerPr() != null) {
getFragmentRefreshListenerPr().onRefresh("closed"); getFragmentRefreshListenerPr().onRefresh("closed");
} }
break; break;
case "openMilestone": case "openMilestone":
if(getFragmentRefreshListenerMilestone() != null) { if(getFragmentRefreshListenerMilestone() != null) {
getFragmentRefreshListenerMilestone().onRefresh("open"); getFragmentRefreshListenerMilestone().onRefresh("open");
} }
break; break;
case "closedMilestone": case "closedMilestone":
if(getFragmentRefreshListenerMilestone() != null) { if(getFragmentRefreshListenerMilestone() != null) {
getFragmentRefreshListenerMilestone().onRefresh("closed"); getFragmentRefreshListenerMilestone().onRefresh("closed");
} }
break; break;
} }
} }
@ -398,54 +385,58 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
@Override @Override
public Fragment getItem(int position) { 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; Fragment fragment = null;
switch(position) { switch(position) {
case 0: // information
return RepoInfoFragment.newInstance(repoOwner, repoName); case 0: // Repository details
case 1: // files return RepoInfoFragment.newInstance(repositoryOwner, repositoryName);
return FilesFragment.newInstance(repoOwner, repoName);
case 2: // issues case 1: // Files
return FilesFragment.newInstance(repositoryOwner, repositoryName);
case 2: // Issues
fragment = new IssuesFragment(); fragment = new IssuesFragment();
break; break;
case 3: // pull requests
case 3: // Pull requests
fragment = new PullRequestsFragment(); fragment = new PullRequestsFragment();
break; break;
case 4: // branches
return BranchesFragment.newInstance(repoOwner, repoName); case 4: // Branches
case 5: // releases return BranchesFragment.newInstance(repositoryOwner, repositoryName);
return ReleasesFragment.newInstance(repoOwner, repoName);
case 6: // milestones case 5: // Releases
return ReleasesFragment.newInstance(repositoryOwner, repositoryName);
case 6: // Milestones
fragment = new MilestonesFragment(); fragment = new MilestonesFragment();
break; break;
case 7: // labels
return LabelsFragment.newInstance(repoOwner, repoName); case 7: // Labels
case 8: // collaborators return LabelsFragment.newInstance(repositoryOwner, repositoryName);
return CollaboratorsFragment.newInstance(repoOwner, repoName);
case 8: // Collaborators
return CollaboratorsFragment.newInstance(repositoryOwner, repositoryName);
} }
assert fragment != null; assert fragment != null;
return fragment; return fragment;
} }
@Override @Override
public int getCount() { public int getCount() {
return 9; return tabsCount;
} }
} }
private void getRepoInfo(String instanceUrl, String token, final String owner, String repo) { 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); Call<UserRepositories> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserRepository(token, owner, repo);
call.enqueue(new Callback<UserRepositories>() { call.enqueue(new Callback<UserRepositories>() {
@Override @Override
@ -457,20 +448,23 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
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) { if(repoInfo.getOpen_issues_count() != null) {
textViewBadgeIssue.setVisibility(View.VISIBLE); textViewBadgeIssue.setVisibility(View.VISIBLE);
textViewBadgeIssue.setText(repoInfo.getOpen_issues_count()); textViewBadgeIssue.setText(repoInfo.getOpen_issues_count());
} }
if(repoInfo.getOpen_pull_count() != null) { if(repoInfo.getOpen_pull_count() != null) {
textViewBadgePull.setVisibility(View.VISIBLE); textViewBadgePull.setVisibility(View.VISIBLE);
textViewBadgePull.setText(repoInfo.getOpen_pull_count()); textViewBadgePull.setText(repoInfo.getOpen_pull_count());
} }
if(repoInfo.getRelease_count() != null) { if(repoInfo.getRelease_count() != null) {
textViewBadgeRelease.setVisibility(View.VISIBLE); textViewBadgeRelease.setVisibility(View.VISIBLE);
textViewBadgeRelease.setText(repoInfo.getRelease_count()); textViewBadgeRelease.setText(repoInfo.getRelease_count());
} }
@ -480,6 +474,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
} }
else { else {
Log.e("onFailure", String.valueOf(response.code())); Log.e("onFailure", String.valueOf(response.code()));
} }
@ -497,17 +492,13 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
private void checkRepositoryStarStatus(String instanceUrl, String instanceToken, final String owner, String repo) { private void checkRepositoryStarStatus(String instanceUrl, String instanceToken, final String owner, String repo) {
Call<JsonElement> call; Call<JsonElement> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkRepoStarStatus(instanceToken, owner, repo);
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkRepoStarStatus(instanceToken, owner, repo);
call.enqueue(new Callback<JsonElement>() { call.enqueue(new Callback<JsonElement>() {
@Override @Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) { public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
TinyDB tinyDb = new TinyDB(appCtx); tinyDB.putInt("repositoryStarStatus", response.code());
tinyDb.putInt("repositoryStarStatus", response.code());
} }
@ -525,22 +516,23 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
Call<WatchInfo> call; Call<WatchInfo> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkRepoWatchStatus(instanceToken, owner, repo); call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkRepoWatchStatus(instanceToken, owner, repo);
call.enqueue(new Callback<WatchInfo>() { call.enqueue(new Callback<WatchInfo>() {
@Override @Override
public void onResponse(@NonNull Call<WatchInfo> call, @NonNull retrofit2.Response<WatchInfo> response) { public void onResponse(@NonNull Call<WatchInfo> call, @NonNull retrofit2.Response<WatchInfo> response) {
TinyDB tinyDb = new TinyDB(appCtx);
if(response.code() == 200) { if(response.code() == 200) {
assert response.body() != null; assert response.body() != null;
if(response.body().getSubscribed()) { if(response.body().getSubscribed()) {
tinyDb.putBoolean("repositoryWatchStatus", true); tinyDB.putBoolean("repositoryWatchStatus", true);
} }
} }
else { else {
tinyDb.putBoolean("repositoryWatchStatus", false);
tinyDB.putBoolean("repositoryWatchStatus", false);
} }
} }
@ -554,4 +546,25 @@ 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); }
} }

View File

@ -201,7 +201,7 @@ public class SettingsAppearanceActivity extends BaseActivity {
AlertDialog.Builder hsBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this); AlertDialog.Builder hsBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
hsBuilder.setTitle(R.string.settingshomeScreenSelectorDialogTitle); hsBuilder.setTitle(R.string.settingsHomeScreenSelectorDialogTitle);
if(homeScreenSelectedChoice != -1) { if(homeScreenSelectedChoice != -1) {
hsBuilder.setCancelable(true); hsBuilder.setCancelable(true);
} }

View File

@ -9,6 +9,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -58,6 +59,8 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
private TextView repoStars; private TextView repoStars;
private TextView repoForks; private TextView repoForks;
private TextView repoOpenIssuesCount; private TextView repoOpenIssuesCount;
private TextView repoType;
private LinearLayout archiveRepo;
private ReposSearchViewHolder(View itemView) { private ReposSearchViewHolder(View itemView) {
@ -73,6 +76,8 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
repoForks = itemView.findViewById(R.id.repoForks); repoForks = itemView.findViewById(R.id.repoForks);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount); repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu); ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
itemView.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
@ -150,7 +155,7 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
TextView repoWatchers = view.findViewById(R.id.repoWatchers); TextView repoWatchers = view.findViewById(R.id.repoWatchers);
TextView bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader); 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); BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view); dialog.setContentView(view);
dialog.show(); dialog.show();
@ -230,9 +235,11 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
holder.fullName.setText(currentItem.getFullname()); holder.fullName.setText(currentItem.getFullname());
if(currentItem.getPrivateFlag()) { if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold); holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold);
holder.repoType.setText(R.string.strPrivate);
} }
else { else {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_public); holder.repoPrivatePublic.setImageResource(R.drawable.ic_public);
holder.repoType.setText(R.string.strPublic);
} }
holder.repoStars.setText(currentItem.getStars_count()); holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count()); holder.repoForks.setText(currentItem.getForks_count());
@ -242,6 +249,13 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
} }
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin()); holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
} }
@Override @Override

View File

@ -165,6 +165,7 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
holder.fileInfo.setText(AppUtil.formatFileSizeInDetail(currentItem.getSize())); holder.fileInfo.setText(AppUtil.formatFileSizeInDetail(currentItem.getSize()));
} }
else if(currentItem.getType().equals("dir")) { else if(currentItem.getType().equals("dir")) {
holder.fileInfo.setVisibility(View.GONE);
holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_folder_24)); holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_folder_24));
} }
else { else {

View File

@ -86,7 +86,7 @@ public class FilesDiffAdapter extends BaseAdapter {
FileDiffView data = (FileDiffView) getItem(position); FileDiffView data = (FileDiffView) getItem(position);
headerFileName.setText(data.getFileName()); headerFileName.setText(data.getFileName());
if(data.isFileType()) { if(data.isFileBinary()) {
diffStats.setVisibility(View.GONE); diffStats.setVisibility(View.GONE);
diffLines.addView(getMessageView(context.getResources().getString(R.string.binaryFileError))); diffLines.addView(getMessageView(context.getResources().getString(R.string.binaryFileError)));
@ -97,7 +97,7 @@ public class FilesDiffAdapter extends BaseAdapter {
diffStats.setVisibility(View.VISIBLE); diffStats.setVisibility(View.VISIBLE);
headerFileInfo.setText(data.getFileInfo()); headerFileInfo.setText(data.getFileInfo());
String[] codeLines = getLines(data.getFileContents()); String[] codeLines = getLines(data.toString());
if(MAXIMUM_LINES > codeLines.length) { if(MAXIMUM_LINES > codeLines.length) {

View File

@ -1,6 +1,8 @@
package org.mian.gitnex.adapters; package org.mian.gitnex.adapters;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@ -104,6 +106,8 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
TextView commentMenuEdit = view.findViewById(R.id.commentMenuEdit); TextView commentMenuEdit = view.findViewById(R.id.commentMenuEdit);
TextView commentShare = view.findViewById(R.id.issueCommentShare); TextView commentShare = view.findViewById(R.id.issueCommentShare);
TextView commentMenuQuote = view.findViewById(R.id.commentMenuQuote);
TextView commentMenuCopy = view.findViewById(R.id.commentMenuCopy);
TextView commentMenuDelete = view.findViewById(R.id.commentMenuDelete); TextView commentMenuDelete = view.findViewById(R.id.commentMenuDelete);
if(!loginUid.contentEquals(commenterUsername.getText())) { if(!loginUid.contentEquals(commenterUsername.getText())) {
@ -111,6 +115,10 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
commentMenuDelete.setVisibility(View.GONE); commentMenuDelete.setVisibility(View.GONE);
} }
if(issueComment.getText().toString().isEmpty()) {
commentMenuCopy.setVisibility(View.GONE);
}
BottomSheetDialog dialog = new BottomSheetDialog(ctx); BottomSheetDialog dialog = new BottomSheetDialog(ctx);
dialog.setContentView(view); dialog.setContentView(view);
dialog.show(); dialog.show();
@ -143,6 +151,48 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
}); });
commentMenuQuote.setOnClickListener(v1 -> {
StringBuilder stringBuilder = new StringBuilder();
String commenterName = commenterUsername.getText().toString();
if(!commenterName.equals(tinyDb.getString("userLogin"))) {
stringBuilder.append("@").append(commenterName).append("\n\n");
}
String[] lines = commendBodyRaw.getText().toString().split("\\R");
for(String line : lines) {
stringBuilder.append(">").append(line).append("\n");
}
stringBuilder.append("\n");
Intent intent = new Intent(ctx, ReplyToIssueActivity.class);
intent.putExtra("commentBody", stringBuilder.toString());
intent.putExtra("cursorToEnd", true);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialog.dismiss();
ctx.startActivity(intent);
});
commentMenuCopy.setOnClickListener(view1 -> {
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
assert clipboard != null;
ClipData clip = ClipData.newPlainText("Comment on issue #" + issueNumber.getText().toString(), issueComment.getText().toString());
clipboard.setPrimaryClip(clip);
dialog.dismiss();
Toasty.info(ctx, ctx.getString(R.string.copyIssueCommentToastMsg));
});
commentMenuDelete.setOnClickListener(deleteComment -> { commentMenuDelete.setOnClickListener(deleteComment -> {
deleteIssueComment(ctx, Integer.parseInt(commendId.getText().toString()), getAdapterPosition()); deleteIssueComment(ctx, Integer.parseInt(commendId.getText().toString()), getAdapterPosition());

View File

@ -3,26 +3,25 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Typeface;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; 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 com.google.android.material.bottomsheet.BottomSheetDialog;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.CreateLabelActivity; import org.mian.gitnex.activities.CreateLabelActivity;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.ColorInverter; import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.helpers.LabelWidthCalculator;
import org.mian.gitnex.models.Labels; import org.mian.gitnex.models.Labels;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
/** /**
* Author M M Arif * Author M M Arif
@ -39,12 +38,17 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
private TextView labelTitle; private TextView labelTitle;
private TextView labelId; private TextView labelId;
private TextView labelColor; private TextView labelColor;
private ImageView labelsView;
private CardView labelView;
private ImageView labelIcon;
private TextView labelName;
private LabelsViewHolder(View itemView) { private LabelsViewHolder(View itemView) {
super(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); ImageView labelsOptionsMenu = itemView.findViewById(R.id.labelsOptionsMenu);
labelTitle = itemView.findViewById(R.id.labelTitle); labelTitle = itemView.findViewById(R.id.labelTitle);
labelId = itemView.findViewById(R.id.labelId); labelId = itemView.findViewById(R.id.labelId);
@ -119,19 +123,13 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
String labelName = currentItem.getName(); String labelName = currentItem.getName();
int color = Color.parseColor("#" + labelColor); int color = Color.parseColor("#" + labelColor);
int contrastColor = new ColorInverter().getContrastColor(color);
TextDrawable drawable = TextDrawable.builder() ImageViewCompat.setImageTintList(holder.labelIcon, ColorStateList.valueOf(contrastColor));
.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);
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(); return labelsList.size();
} }
} }

View File

@ -2,7 +2,6 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.text.Spanned; import android.text.Spanned;
@ -15,7 +14,6 @@ import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.google.android.material.bottomsheet.BottomSheetDialog; import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.vdurmont.emoji.EmojiParser; import com.vdurmont.emoji.EmojiParser;
import org.mian.gitnex.R; import org.mian.gitnex.R;
@ -56,369 +54,346 @@ import io.noties.markwon.linkify.LinkifyPlugin;
public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context; private Context context;
private final int TYPE_LOAD = 0; private final int TYPE_LOAD = 0;
private List<Milestones> dataList; private List<Milestones> dataList;
private OnLoadMoreListener loadMoreListener; private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false; private boolean isLoading = false;
private boolean isMoreDataAvailable = true; private boolean isMoreDataAvailable = true;
private String TAG = StaticGlobalVariables.tagMilestonesAdapter; private String TAG = StaticGlobalVariables.tagMilestonesAdapter;
public MilestonesAdapter(Context context, List<Milestones> dataListMain) { public MilestonesAdapter(Context context, List<Milestones> dataListMain) {
this.context = context; this.context = context;
this.dataList = dataListMain; this.dataList = dataListMain;
} }
@NonNull @NonNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context); LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD) { if(viewType == TYPE_LOAD) {
return new MilestonesAdapter.DataHolder(inflater.inflate(R.layout.list_milestones, parent, false)); return new MilestonesAdapter.DataHolder(inflater.inflate(R.layout.list_milestones, parent, false));
} }
else { else {
return new MilestonesAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false)); return new MilestonesAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
} }
} }
@Override @Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) { if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true; isLoading = true;
loadMoreListener.onLoadMore(); loadMoreListener.onLoadMore();
} }
if(getItemViewType(position) == TYPE_LOAD) { if(getItemViewType(position) == TYPE_LOAD) {
((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 milestoneId;
private TextView msTitle; private TextView msTitle;
private TextView msDescription; private TextView msDescription;
private TextView msOpenIssues; private TextView msOpenIssues;
private TextView msClosedIssues; private TextView msClosedIssues;
private TextView msDueDate; private TextView msDueDate;
private ImageView msStatus; private ProgressBar msProgress;
private ProgressBar msProgress; private TextView milestoneStatus;
private TextView milestoneStatus;
DataHolder(View itemView) { DataHolder(View itemView) {
super(itemView); super(itemView);
milestoneId = itemView.findViewById(R.id.milestoneId); milestoneId = itemView.findViewById(R.id.milestoneId);
msTitle = itemView.findViewById(R.id.milestoneTitle); msTitle = itemView.findViewById(R.id.milestoneTitle);
msStatus = itemView.findViewById(R.id.milestoneState); msDescription = itemView.findViewById(R.id.milestoneDescription);
msDescription = itemView.findViewById(R.id.milestoneDescription); msOpenIssues = itemView.findViewById(R.id.milestoneIssuesOpen);
msOpenIssues = itemView.findViewById(R.id.milestoneIssuesOpen); msClosedIssues = itemView.findViewById(R.id.milestoneIssuesClosed);
msClosedIssues = itemView.findViewById(R.id.milestoneIssuesClosed); msDueDate = itemView.findViewById(R.id.milestoneDueDate);
msDueDate = itemView.findViewById(R.id.milestoneDueDate); msProgress = itemView.findViewById(R.id.milestoneProgress);
msProgress = itemView.findViewById(R.id.milestoneProgress); ImageView milestonesMenu = itemView.findViewById(R.id.milestonesMenu);
ImageView milestonesMenu = itemView.findViewById(R.id.milestonesMenu); milestoneStatus = itemView.findViewById(R.id.milestoneStatus);
milestoneStatus = itemView.findViewById(R.id.milestoneStatus);
milestonesMenu.setOnClickListener(v -> { milestonesMenu.setOnClickListener(v -> {
Context ctx = v.getContext(); Context ctx = v.getContext();
int milestoneId_ = Integer.parseInt(milestoneId.getText().toString()); int milestoneId_ = Integer.parseInt(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 closeMilestone = view.findViewById(R.id.closeMilestone);
TextView openMilestone = view.findViewById(R.id.openMilestone); TextView openMilestone = view.findViewById(R.id.openMilestone);
BottomSheetDialog dialog = new BottomSheetDialog(ctx); BottomSheetDialog dialog = new BottomSheetDialog(ctx);
dialog.setContentView(view); dialog.setContentView(view);
dialog.show(); dialog.show();
if(milestoneStatus.getText().toString().equals("open")) { if(milestoneStatus.getText().toString().equals("open")) {
closeMilestone.setVisibility(View.VISIBLE); closeMilestone.setVisibility(View.VISIBLE);
openMilestone.setVisibility(View.GONE); openMilestone.setVisibility(View.GONE);
} }
else { else {
closeMilestone.setVisibility(View.GONE); closeMilestone.setVisibility(View.GONE);
openMilestone.setVisibility(View.VISIBLE); openMilestone.setVisibility(View.VISIBLE);
} }
closeMilestone.setOnClickListener(v12 -> { closeMilestone.setOnClickListener(v12 -> {
MilestoneActions.closeMilestone(ctx, milestoneId_); MilestoneActions.closeMilestone(ctx, milestoneId_);
dialog.dismiss(); dialog.dismiss();
updateAdapter(getAdapterPosition()); updateAdapter(getAdapterPosition());
}); });
openMilestone.setOnClickListener(v12 -> { openMilestone.setOnClickListener(v12 -> {
MilestoneActions.openMilestone(ctx, milestoneId_); MilestoneActions.openMilestone(ctx, milestoneId_);
dialog.dismiss(); dialog.dismiss();
updateAdapter(getAdapterPosition()); 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())); @SuppressLint("SetTextI18n")
milestoneStatus.setText(dataModel.getState()); void bindData(Milestones dataModel) {
final Markwon markwon = Markwon.builder(Objects.requireNonNull(context)) final TinyDB tinyDb = new TinyDB(context);
.usePlugin(CorePlugin.create()) final String locale = tinyDb.getString("locale");
.usePlugin(ImagesPlugin.create(plugin -> { final String timeFormat = tinyDb.getString("dateFormat");
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);
if(date.before(new Date())) { milestoneId.setText(String.valueOf(dataModel.getId()));
msDueDate.setTextColor(context.getResources().getColor(R.color.darkRed)); milestoneStatus.setText(dataModel.getState());
}
msDueDate.setText(dueDate); Markwon markwon = Markwon.builder(Objects.requireNonNull(context)).usePlugin(CorePlugin.create()).usePlugin(ImagesPlugin.create(plugin -> {
msDueDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToast(dataModel.getDue_on()), context)); plugin.addSchemeHandler(new SchemeHandler() {
} @NonNull
else if (timeFormat.equals("normal1")) { @Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", new Locale(locale)); final int resourceId = context.getResources().getIdentifier(
Date date1 = null; raw.substring("drawable://".length()),
try { "drawable",
date1 = formatter.parse(dataModel.getDue_on()); context.getPackageName());
}
catch (ParseException e) {
Log.e(TAG, e.toString());
}
assert date1 != null;
String dueDate = formatter.format(date1);
msDueDate.setText(dueDate);
} final Drawable drawable = context.getDrawable(resourceId);
} assert drawable != null;
else { return ImageItem.withResult(drawable);
msDueDate.setText(""); }
}
} @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());
private void updateAdapter(int position) { }))
dataList.remove(position); .usePlugin(new AbstractMarkwonPlugin() {
notifyItemRemoved(position); @Override
notifyItemRangeChanged(position, dataList.size()); 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_);
@Override if(!dataModel.getDescription().equals("")) {
public int getItemViewType(int position) {
if(dataList.get(position).getTitle() != null) { CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(dataModel.getDescription()));
return TYPE_LOAD; msDescription.setText(bodyWithMD);
}
else {
return 1;
}
} }
else {
@Override msDescription.setText(context.getString(R.string.milestoneNoDescription));
public int getItemCount() { }
return dataList.size(); 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) {
static class LoadHolder extends RecyclerView.ViewHolder { if(dataModel.getOpen_issues() == 0) {
LoadHolder(View itemView) { msProgress.setProgress(100);
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 100), context));
super(itemView); }
} 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);
public void setMoreDataAvailable(boolean moreDataAvailable) { }
isMoreDataAvailable = moreDataAvailable; }
else {
} msProgress.setProgress(0);
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 0), context));
public void notifyDataChanged() { }
notifyDataSetChanged(); if(dataModel.getDue_on() != null) {
isLoading = false;
} if(timeFormat.equals("normal") || timeFormat.equals("pretty")) {
public interface OnLoadMoreListener { DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", new Locale(locale));
Date date = null;
void onLoadMore(); try {
date = formatter.parse(dataModel.getDue_on());
}
catch(ParseException e) {
Log.e(TAG, e.toString());
}
} assert date != null;
String dueDate = formatter.format(date);
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) { if(date.before(new Date())) {
msDueDate.setTextColor(context.getResources().getColor(R.color.darkRed));
}
this.loadMoreListener = loadMoreListener; msDueDate.setText(dueDate);
msDueDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToast(dataModel.getDue_on()), context));
} }
else if(timeFormat.equals("normal1")) {
public void updateList(List<Milestones> list) { SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", new Locale(locale));
dataList = list; Date date1 = null;
notifyDataSetChanged();
} 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);
}
}
else {
msDueDate.setText(context.getString(R.string.milestoneNoDueDate));
}
}
}
private void updateAdapter(int position) {
dataList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, dataList.size());
}
@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

@ -11,6 +11,7 @@ import android.widget.CheckBox;
import android.widget.Filter; import android.widget.Filter;
import android.widget.Filterable; import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator; import com.amulyakhare.textdrawable.util.ColorGenerator;
@ -56,6 +57,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
private TextView repoOpenIssuesCount; private TextView repoOpenIssuesCount;
private TextView repoType; private TextView repoType;
private CheckBox isRepoAdmin; private CheckBox isRepoAdmin;
private LinearLayout archiveRepo;
private MyReposViewHolder(View itemView) { private MyReposViewHolder(View itemView) {
super(itemView); super(itemView);
@ -70,6 +72,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu); ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType); repoType = itemView.findViewById(R.id.repoType);
isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin); isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
itemView.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
@ -148,7 +151,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
TextView repoWatchers = view.findViewById(R.id.repoWatchers); TextView repoWatchers = view.findViewById(R.id.repoWatchers);
TextView bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader); TextView bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader);
bottomSheetHeader.setText(repoFullName.getText()); bottomSheetHeader.setText(String.format("%s / %s", repoFullName.getText().toString().split("/")[0], repoFullName.getText().toString().split("/")[1]));
BottomSheetDialog dialog = new BottomSheetDialog(context); BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view); dialog.setContentView(view);
dialog.show(); dialog.show();
@ -252,6 +255,13 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
} }
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin()); holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
} }
@Override @Override

View File

@ -188,9 +188,18 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
prNumber.setText(String.valueOf(prModel.getNumber())); prNumber.setText(String.valueOf(prModel.getNumber()));
prMergeable.setText(String.valueOf(prModel.isMergeable())); prMergeable.setText(String.valueOf(prModel.isMergeable()));
prHeadBranch.setText(prModel.getHead().getRef()); if(prModel.getHead() != null) {
prIsFork.setText(String.valueOf(prModel.getHead().getRepo().isFork())); prHeadBranch.setText(prModel.getHead().getRef());
prForkFullName.setText(prModel.getHead().getRepo().getFull_name()); 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())); prCommentsCount.setText(String.valueOf(prModel.getComments()));
prCreatedTime.setText(TimeHelper.formatTime(prModel.getCreated_at(), new Locale(locale), timeFormat, context)); prCreatedTime.setText(TimeHelper.formatTime(prModel.getCreated_at(), new Locale(locale), timeFormat, context));

View File

@ -10,19 +10,25 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import com.amulyakhare.textdrawable.TextDrawable; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.vdurmont.emoji.EmojiParser; import com.vdurmont.emoji.EmojiParser;
import org.mian.gitnex.R; import org.mian.gitnex.R;
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.models.Releases; import org.mian.gitnex.models.Releases;
import org.mian.gitnex.util.TinyDB; import org.mian.gitnex.util.TinyDB;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon; import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin; import io.noties.markwon.core.CorePlugin;
@ -31,7 +37,6 @@ import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin; import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tasklist.TaskListPlugin; import io.noties.markwon.ext.tasklist.TaskListPlugin;
import io.noties.markwon.html.HtmlPlugin; import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.AsyncDrawable;
import io.noties.markwon.image.DefaultMediaDecoder; import io.noties.markwon.image.DefaultMediaDecoder;
import io.noties.markwon.image.ImageItem; import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin; import io.noties.markwon.image.ImagesPlugin;
@ -49,25 +54,44 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
private List<Releases> releasesList; private List<Releases> releasesList;
private Context mCtx; private Context mCtx;
static class ReleasesViewHolder extends RecyclerView.ViewHolder { static class ReleasesViewHolder extends RecyclerView.ViewHolder {
private ImageView releaseType; private TextView releaseType;
private TextView releaseTitle; private TextView releaseName;
private TextView releaseDescription; private ImageView authorAvatar;
private TextView releaseDownload; private TextView authorName;
private TextView releaseZipDownload;
private TextView releaseTarDownload;
private TextView releaseTag; 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) { private ReleasesViewHolder(View itemView) {
super(itemView); super(itemView);
releaseType = itemView.findViewById(R.id.releaseType); releaseType = itemView.findViewById(R.id.releaseType);
releaseTitle = itemView.findViewById(R.id.releaseTitle); releaseName = itemView.findViewById(R.id.releaseName);
releaseDescription = itemView.findViewById(R.id.releaseDescription); authorAvatar = itemView.findViewById(R.id.authorAvatar);
releaseZipDownload = itemView.findViewById(R.id.releaseZipDownload); authorName = itemView.findViewById(R.id.authorName);
releaseTarDownload = itemView.findViewById(R.id.releaseTarDownload); releaseTag = itemView.findViewById(R.id.releaseTag);
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()));
} }
} }
@ -88,83 +112,74 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
public void onBindViewHolder(@NonNull ReleasesAdapter.ReleasesViewHolder holder, int position) { public void onBindViewHolder(@NonNull ReleasesAdapter.ReleasesViewHolder holder, int position) {
final TinyDB tinyDb = new TinyDB(mCtx); final TinyDB tinyDb = new TinyDB(mCtx);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
Releases currentItem = releasesList.get(position); Releases currentItem = releasesList.get(position);
holder.releaseTitle.setText(currentItem.getName()); holder.releaseName.setText(currentItem.getName());
if(!currentItem.getTag_name().equals("")) { if(currentItem.isPrerelease()) {
holder.releaseTag.setText(mCtx.getResources().getString(R.string.releaseTag, currentItem.getTag_name())); holder.releaseType.setBackgroundResource(R.drawable.shape_pre_release);
} holder.releaseType.setText(R.string.releaseTypePre);
else { }
holder.releaseTag.setVisibility(View.GONE); 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()) { if(currentItem.getAuthor().getAvatar_url() != null) {
TextDrawable drawable = TextDrawable.builder() 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);
.beginConfig() }
//.useFont(Typeface.DEFAULT)
.textColor(mCtx.getResources().getColor(R.color.white)) holder.authorName.setText(mCtx.getResources().getString(R.string.releasePublishedBy, currentItem.getAuthor().getUsername()));
.fontSize(34)
.width(260) if(currentItem.getTag_name() != null) {
.height(60) holder.releaseTag.setText(currentItem.getTag_name());
.endConfig() }
.buildRoundRect(mCtx.getResources().getString(R.string.releaseTypePre), mCtx.getResources().getColor(R.color.releasePre), 8);
holder.releaseType.setImageDrawable(drawable); if(currentItem.getPublished_at() != null) {
} holder.releaseDate.setText(TimeHelper.formatTime(currentItem.getPublished_at(), new Locale(locale), timeFormat, mCtx));
else { }
TextDrawable drawable = TextDrawable.builder()
.beginConfig() if(timeFormat.equals("pretty")) {
//.useFont(Typeface.DEFAULT) holder.releaseDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getPublished_at()), mCtx));
.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);
}
final Markwon markwon = Markwon.builder(Objects.requireNonNull(mCtx)) final Markwon markwon = Markwon.builder(Objects.requireNonNull(mCtx))
.usePlugin(CorePlugin.create()) .usePlugin(CorePlugin.create())
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() { .usePlugin(ImagesPlugin.create(plugin -> {
@Override plugin.addSchemeHandler(new SchemeHandler() {
public void configureImages(@NonNull ImagesPlugin plugin) { @NonNull
plugin.addSchemeHandler(new SchemeHandler() { @Override
@NonNull public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = mCtx.getResources().getIdentifier( final int resourceId = mCtx.getResources().getIdentifier(
raw.substring("drawable://".length()), raw.substring("drawable://".length()),
"drawable", "drawable",
mCtx.getPackageName()); mCtx.getPackageName());
final Drawable drawable = mCtx.getDrawable(resourceId); final Drawable drawable = mCtx.getDrawable(resourceId);
assert drawable != null; assert drawable != null;
return ImageItem.withResult(drawable); return ImageItem.withResult(drawable);
} }
@NonNull @NonNull
@Override @Override
public Collection<String> supportedSchemes() { public Collection<String> supportedSchemes() {
return Collections.singleton("drawable"); return Collections.singleton("drawable");
} }
}); });
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() { plugin.placeholderProvider(drawable -> null);
@Nullable plugin.addMediaDecoder(GifMediaDecoder.create(false));
@Override plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources()));
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) { plugin.addMediaDecoder(SvgMediaDecoder.create());
return null; plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources()));
} plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
});
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() { .usePlugin(new AbstractMarkwonPlugin() {
@Override @Override
@ -185,12 +200,29 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(currentItem.getBody())); Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(currentItem.getBody()));
if(!currentItem.getBody().equals("")) { if(!currentItem.getBody().equals("")) {
markwon.setParsedMarkdown(holder.releaseDescription, bodyWithMD); markwon.setParsedMarkdown(holder.releaseBodyContent, bodyWithMD);
} }
else { 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_arrow_down);
holder.downloads.setVisibility(View.VISIBLE);
}
else {
holder.downloadDropdownIcon.setImageResource(R.drawable.ic_arrow_right);
holder.downloads.setVisibility(View.GONE);
}
});
holder.releaseZipDownload.setText( holder.releaseZipDownload.setText(
Html.fromHtml("<a href='" + currentItem.getZipball_url() + "'>" + mCtx.getResources().getString(R.string.zipArchiveDownloadReleasesTab) + "</a> ")); Html.fromHtml("<a href='" + currentItem.getZipball_url() + "'>" + mCtx.getResources().getString(R.string.zipArchiveDownloadReleasesTab) + "</a> "));
holder.releaseZipDownload.setMovementMethod(LinkMovementMethod.getInstance()); holder.releaseZipDownload.setMovementMethod(LinkMovementMethod.getInstance());
@ -199,6 +231,9 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
Html.fromHtml("<a href='" + currentItem.getTarball_url() + "'>" + mCtx.getResources().getString(R.string.tarArchiveDownloadReleasesTab) + "</a> ")); Html.fromHtml("<a href='" + currentItem.getTarball_url() + "'>" + mCtx.getResources().getString(R.string.tarArchiveDownloadReleasesTab) + "</a> "));
holder.releaseTarDownload.setMovementMethod(LinkMovementMethod.getInstance()); holder.releaseTarDownload.setMovementMethod(LinkMovementMethod.getInstance());
ReleasesDownloadsAdapter adapter = new ReleasesDownloadsAdapter(currentItem.getAssets());
holder.downloadList.setAdapter(adapter);
} }
@Override @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

@ -109,13 +109,6 @@ public class RepoStargazersAdapter extends BaseAdapter {
viewHolder.memberName.setTypeface(myTypeface); 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

@ -109,13 +109,6 @@ public class RepoWatchersAdapter extends BaseAdapter {
viewHolder.memberName.setTypeface(myTypeface); 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

@ -11,6 +11,7 @@ import android.widget.CheckBox;
import android.widget.Filter; import android.widget.Filter;
import android.widget.Filterable; import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -56,6 +57,7 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
private TextView repoForks; private TextView repoForks;
private TextView repoOpenIssuesCount; private TextView repoOpenIssuesCount;
private TextView repoType; private TextView repoType;
private LinearLayout archiveRepo;
private ReposViewHolder(View itemView) { private ReposViewHolder(View itemView) {
@ -71,6 +73,7 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount); repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu); ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType); repoType = itemView.findViewById(R.id.repoType);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
itemView.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
@ -150,7 +153,7 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
TextView repoWatchers = view.findViewById(R.id.repoWatchers); TextView repoWatchers = view.findViewById(R.id.repoWatchers);
TextView bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader); 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); BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view); dialog.setContentView(view);
dialog.show(); dialog.show();
@ -249,6 +252,13 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
} }
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin()); holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
} }
@Override @Override

View File

@ -11,6 +11,7 @@ import android.widget.CheckBox;
import android.widget.Filter; import android.widget.Filter;
import android.widget.Filterable; import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator; import com.amulyakhare.textdrawable.util.ColorGenerator;
@ -56,6 +57,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
private TextView repoForks; private TextView repoForks;
private TextView repoOpenIssuesCount; private TextView repoOpenIssuesCount;
private TextView repoType; private TextView repoType;
private LinearLayout archiveRepo;
private OrgReposViewHolder(View itemView) { private OrgReposViewHolder(View itemView) {
super(itemView); super(itemView);
@ -70,6 +72,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount); repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu); ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType); repoType = itemView.findViewById(R.id.repoType);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
itemView.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
@ -147,7 +150,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
TextView repoWatchers = view.findViewById(R.id.repoWatchers); TextView repoWatchers = view.findViewById(R.id.repoWatchers);
TextView bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader); 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); BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view); dialog.setContentView(view);
dialog.show(); dialog.show();
@ -252,6 +255,13 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
} }
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin()); holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
} }
@Override @Override

View File

@ -11,6 +11,7 @@ import android.widget.CheckBox;
import android.widget.Filter; import android.widget.Filter;
import android.widget.Filterable; import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator; import com.amulyakhare.textdrawable.util.ColorGenerator;
@ -56,6 +57,7 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
private TextView repoForks; private TextView repoForks;
private TextView repoOpenIssuesCount; private TextView repoOpenIssuesCount;
private TextView repoType; private TextView repoType;
private LinearLayout archiveRepo;
private StarredReposViewHolder(View itemView) { private StarredReposViewHolder(View itemView) {
super(itemView); super(itemView);
@ -70,6 +72,7 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount); repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu); ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType); repoType = itemView.findViewById(R.id.repoType);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
itemView.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
@ -148,7 +151,7 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
TextView repoWatchers = view.findViewById(R.id.repoWatchers); TextView repoWatchers = view.findViewById(R.id.repoWatchers);
TextView bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader); 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); BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view); dialog.setContentView(view);
dialog.show(); dialog.show();
@ -252,6 +255,13 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
} }
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin()); holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
} }
@Override @Override

View File

@ -111,12 +111,5 @@ public class TeamMembersByOrgAdapter extends BaseAdapter {
viewHolder.memberName.setTypeface(myTypeface); 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

@ -104,12 +104,11 @@ public class UserSearchForTeamMemberAdapter extends RecyclerView.Adapter<UserSea
if (!currentItem.getFullname().equals("")) { if (!currentItem.getFullname().equals("")) {
holder.userFullName.setText(currentItem.getFullname()); holder.userFullName.setText(currentItem.getFullname());
holder.userName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getLogin()));
} }
else { else {
holder.userFullName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getLogin())); holder.userFullName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getLogin()));
holder.userName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getLogin()));
} }
holder.userName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getLogin()));
if (!currentItem.getAvatar().equals("")) { if (!currentItem.getAvatar().equals("")) {
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar); PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
@ -123,7 +122,6 @@ public class UserSearchForTeamMemberAdapter extends RecyclerView.Adapter<UserSea
String repoFullName = tinyDb.getString("repoFullName"); String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
final String repoOwner = parts[0]; final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
Call<UserInfo> call = RetrofitClient Call<UserInfo> call = RetrofitClient

View File

@ -27,7 +27,7 @@ public class AppApiService {
public static <S> S createService(Class<S> serviceClass, String instanceURL, Context ctx) { public static <S> S createService(Class<S> serviceClass, String instanceURL, Context ctx) {
TinyDB tinyDb = new TinyDB(ctx); TinyDB tinyDb = new TinyDB(ctx);
final boolean connToInternet = AppUtil.haveNetworkConnection(ctx); final boolean connToInternet = AppUtil.hasNetworkConnection(ctx);
File httpCacheDirectory = new File(ctx.getCacheDir(), "responses"); File httpCacheDirectory = new File(ctx.getCacheDir(), "responses");
int cacheSize = FilesData.returnOnlyNumber(tinyDb.getString("cacheSizeStr")) * 1024 * 1024; int cacheSize = FilesData.returnOnlyNumber(tinyDb.getString("cacheSizeStr")) * 1024 * 1024;
Cache cache = new Cache(httpCacheDirectory, cacheSize); Cache cache = new Cache(httpCacheDirectory, cacheSize);

View File

@ -14,16 +14,18 @@ import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
/** /**
* Author anonTree1417 * Author opyale
*/ */
public class PicassoService { public class PicassoService {
private static PicassoService picassoService; private static PicassoService picassoService;
private static File cachePath;
private Picasso picasso; private Picasso picasso;
private PicassoService(Context context) { private PicassoService(Context context) {
cachePath = new File(context.getCacheDir() + "/picasso_cache/");
Picasso.Builder builder = new Picasso.Builder(context); Picasso.Builder builder = new Picasso.Builder(context);
try { try {
@ -45,10 +47,6 @@ public class PicassoService {
}); });
File cachePath = new File(context.getCacheDir() + "/picasso_cache/");
//noinspection ResultOfMethodCallIgnored
cachePath.mkdirs();
picasso = builder.memoryCache(new PicassoCache(cachePath, context)).build(); picasso = builder.memoryCache(new PicassoCache(cachePath, context)).build();
} }
@ -61,7 +59,9 @@ public class PicassoService {
public Picasso get() { public Picasso get() {
cachePath.mkdirs();
return picasso; return picasso;
} }
public static synchronized PicassoService getInstance(Context context) { public static synchronized PicassoService getInstance(Context context) {

View File

@ -32,7 +32,7 @@ public class RetrofitClient {
private RetrofitClient(String instanceUrl, Context ctx) { private RetrofitClient(String instanceUrl, Context ctx) {
TinyDB tinyDb = new TinyDB(ctx); TinyDB tinyDb = new TinyDB(ctx);
final boolean connToInternet = AppUtil.haveNetworkConnection(ctx); final boolean connToInternet = AppUtil.hasNetworkConnection(ctx);
int cacheSize = FilesData.returnOnlyNumber(tinyDb.getString("cacheSizeStr")) * 1024 * 1024; int cacheSize = FilesData.returnOnlyNumber(tinyDb.getString("cacheSizeStr")) * 1024 * 1024;
File httpCacheDirectory = new File(ctx.getCacheDir(), "responses"); File httpCacheDirectory = new File(ctx.getCacheDir(), "responses");
Cache cache = new Cache(httpCacheDirectory, cacheSize); Cache cache = new Cache(httpCacheDirectory, cacheSize);

View File

@ -71,13 +71,14 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
} }
}); });
addCollaborator.setOnClickListener(new View.OnClickListener() { if (tinyDb.getBoolean("isRepoAdmin")) {
@Override addCollaborator.setOnClickListener(v1 -> {
public void onClick(View v) { bmListener.onButtonClicked("addCollaborator");
bmListener.onButtonClicked("addCollaborator"); dismiss();
dismiss(); });
} } else {
}); addCollaborator.setVisibility(View.GONE);
}
createRelease.setOnClickListener(new View.OnClickListener() { createRelease.setOnClickListener(new View.OnClickListener() {
@Override @Override

View File

@ -19,10 +19,14 @@ import org.mian.gitnex.activities.AddRemoveLabelsActivity;
import org.mian.gitnex.activities.EditIssueActivity; import org.mian.gitnex.activities.EditIssueActivity;
import org.mian.gitnex.activities.FileDiffActivity; import org.mian.gitnex.activities.FileDiffActivity;
import org.mian.gitnex.activities.MergePullRequestActivity; import org.mian.gitnex.activities.MergePullRequestActivity;
import org.mian.gitnex.helpers.PathsHelper;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.util.TinyDB; import org.mian.gitnex.util.TinyDB;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Objects; import java.util.Objects;
import io.mikael.urlbuilder.UrlBuilder;
/** /**
* Author M M Arif * Author M M Arif
@ -64,7 +68,10 @@ public class BottomSheetSingleIssueFragment extends BottomSheetDialogFragment {
mergePullRequest.setVisibility(View.VISIBLE); mergePullRequest.setVisibility(View.VISIBLE);
} }
if(tinyDB.getString("repoType").equals("public")) { if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.13.0")) {
openFilesDiff.setVisibility(View.VISIBLE);
}
else if(tinyDB.getString("repoType").equals("public")) {
openFilesDiff.setVisibility(View.VISIBLE); openFilesDiff.setVisibility(View.VISIBLE);
} }
else { else {
@ -135,53 +142,61 @@ public class BottomSheetSingleIssueFragment extends BottomSheetDialogFragment {
shareIssue.setOnClickListener(v1 -> { shareIssue.setOnClickListener(v1 -> {
// get url of repo try {
String repoFullName = tinyDB.getString("repoFullName");
String instanceUrlWithProtocol = "https://" + tinyDB.getString("instanceUrlRaw"); URI instanceUrl = new URI(tinyDB.getString("instanceUrlWithProtocol"));
if(!tinyDB.getString("instanceUrlWithProtocol").isEmpty()) {
instanceUrlWithProtocol = tinyDB.getString("instanceUrlWithProtocol"); String issuePath = PathsHelper.join(instanceUrl.getPath(), tinyDB.getString("repoFullName"), "/issues/", tinyDB.getString("issueNumber"));
String issueUrl = UrlBuilder.fromUri(instanceUrl)
.withPath(issuePath)
.toString();
// share issue
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, getResources().getString(R.string.hash) + tinyDB.getString("issueNumber") + " " + tinyDB.getString("issueTitle"));
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, issueUrl);
startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.hash) + tinyDB.getString("issueNumber") + " " + tinyDB.getString("issueTitle")));
}
catch(URISyntaxException e) {
Toasty.error(ctx, getString(R.string.genericError));
}
finally {
dismiss();
} }
// get issue Url
String issueUrl = instanceUrlWithProtocol + "/" + repoFullName + "/issues/" + tinyDB.getString("issueNumber");
// share issue
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, getResources().getString(R.string.hash) + tinyDB.getString("issueNumber") + " " + tinyDB.getString("issueTitle"));
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, issueUrl);
startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.hash) + tinyDB.getString("issueNumber") + " " + tinyDB.getString("issueTitle")));
dismiss();
}); });
copyIssueUrl.setOnClickListener(new View.OnClickListener() { copyIssueUrl.setOnClickListener(v12 -> {
@Override try {
public void onClick(View v) {
// get url of repo URI instanceUrl = new URI(tinyDB.getString("instanceUrlWithProtocol"));
String repoFullName = tinyDB.getString("repoFullName");
String instanceUrlWithProtocol = "https://" + tinyDB.getString("instanceUrlRaw");
if(!tinyDB.getString("instanceUrlWithProtocol").isEmpty()) {
instanceUrlWithProtocol = tinyDB.getString("instanceUrlWithProtocol");
}
// get issue Url String issuePath = PathsHelper.join(instanceUrl.getPath(), tinyDB.getString("repoFullName"), "/issues/", tinyDB.getString("issueNumber"));
String issueUrl = instanceUrlWithProtocol + "/" + repoFullName + "/issues/" + tinyDB.getString("issueNumber");
String issueUrl = UrlBuilder.fromUri(instanceUrl)
.withPath(issuePath)
.toString();
// copy to clipboard // copy to clipboard
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(android.content.Context.CLIPBOARD_SERVICE); ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("issueUrl", issueUrl); ClipData clip = ClipData.newPlainText("issueUrl", issueUrl);
assert clipboard != null; assert clipboard != null;
clipboard.setPrimaryClip(clip); clipboard.setPrimaryClip(clip);
dismiss();
Toasty.info(ctx, ctx.getString(R.string.copyIssueUrlToastMsg)); Toasty.info(ctx, ctx.getString(R.string.copyIssueUrlToastMsg));
} }
catch(URISyntaxException e) {
Toasty.error(ctx, getString(R.string.genericError));
}
finally {
dismiss();
}
}); });
if(tinyDB.getString("issueType").equals("issue")) { if(tinyDB.getString("issueType").equals("issue")) {

View File

@ -325,6 +325,9 @@ public class IssuesFragment extends Fragment {
List<Issues> arr = new ArrayList<>(); List<Issues> arr = new ArrayList<>();
for(Issues d : issuesList) { for(Issues d : issuesList) {
if(d == null || d.getTitle() == null || d.getBody() == null) {
continue;
}
if(d.getTitle().toLowerCase().contains(text) || d.getBody().toLowerCase().contains(text)) { if(d.getTitle().toLowerCase().contains(text) || d.getBody().toLowerCase().contains(text)) {
arr.add(d); arr.add(d);
} }

View File

@ -104,7 +104,7 @@ public class MembersByOrgFragment extends Fragment {
@Override @Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext())); boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
inflater.inflate(R.menu.search_menu, menu); inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);

View File

@ -77,16 +77,20 @@ public class MilestonesFragment extends Fragment {
dataList = new ArrayList<>(); dataList = new ArrayList<>();
adapter = new MilestonesAdapter(ctx, dataList); adapter = new MilestonesAdapter(ctx, dataList);
adapter.setLoadMoreListener(() -> viewBinding.recyclerView.post(() -> { if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
if(dataList.size() == resultLimit || pageSize == resultLimit) { adapter.setLoadMoreListener(() -> viewBinding.recyclerView.post(() -> {
int page = (dataList.size() + resultLimit) / resultLimit; if(dataList.size() == resultLimit || pageSize == resultLimit) {
loadMore(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, page, resultLimit, tinyDb.getString("milestoneState"));
} int page = (dataList.size() + resultLimit) / resultLimit;
loadMore(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, page, resultLimit, tinyDb.getString("milestoneState"));
})); }
}));
}
viewBinding.recyclerView.setHasFixedSize(true); viewBinding.recyclerView.setHasFixedSize(true);
viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx)); viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
@ -113,16 +117,21 @@ public class MilestonesFragment extends Fragment {
dataList.clear(); dataList.clear();
adapter = new MilestonesAdapter(ctx, dataList); adapter = new MilestonesAdapter(ctx, dataList);
adapter.setLoadMoreListener(() -> viewBinding.recyclerView.post(() -> {
if(dataList.size() == resultLimit || pageSize == resultLimit) { if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
int page = (dataList.size() + resultLimit) / resultLimit; adapter.setLoadMoreListener(() -> viewBinding.recyclerView.post(() -> {
loadMore(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, page, resultLimit, milestoneState);
} if(dataList.size() == resultLimit || pageSize == resultLimit) {
})); int page = (dataList.size() + resultLimit) / resultLimit;
loadMore(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, page, resultLimit, milestoneState);
}
}));
}
tinyDb.putString("milestoneState", milestoneState); tinyDb.putString("milestoneState", milestoneState);
@ -171,7 +180,7 @@ public class MilestonesFragment extends Fragment {
@Override @Override
public void onResponse(@NonNull Call<List<Milestones>> call, @NonNull Response<List<Milestones>> response) { public void onResponse(@NonNull Call<List<Milestones>> call, @NonNull Response<List<Milestones>> response) {
if(response.isSuccessful()) { if(response.code() == 200) {
assert response.body() != null; assert response.body() != null;
if(response.body().size() > 0) { if(response.body().size() > 0) {
@ -222,7 +231,7 @@ public class MilestonesFragment extends Fragment {
@Override @Override
public void onResponse(@NonNull Call<List<Milestones>> call, @NonNull Response<List<Milestones>> response) { public void onResponse(@NonNull Call<List<Milestones>> call, @NonNull Response<List<Milestones>> response) {
if(response.isSuccessful()) { if(response.code() == 200) {
//remove loading view //remove loading view
dataList.remove(dataList.size() - 1); dataList.remove(dataList.size() - 1);
@ -238,7 +247,6 @@ public class MilestonesFragment extends Fragment {
} }
else { else {
Toasty.info(ctx, getString(R.string.noMoreData));
adapter.setMoreDataAvailable(false); adapter.setMoreDataAvailable(false);
} }
@ -310,6 +318,9 @@ public class MilestonesFragment extends Fragment {
List<Milestones> arr = new ArrayList<>(); List<Milestones> arr = new ArrayList<>();
for(Milestones d : dataList) { for(Milestones d : dataList) {
if(d == null || d.getTitle() == null || d.getDescription() == null) {
continue;
}
if(d.getTitle().toLowerCase().contains(text) || d.getDescription().toLowerCase().contains(text)) { if(d.getTitle().toLowerCase().contains(text) || d.getDescription().toLowerCase().contains(text)) {
arr.add(d); arr.add(d);
} }

View File

@ -81,7 +81,7 @@ public class MyRepositoriesFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext())); boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
final View v = inflater.inflate(R.layout.fragment_my_repositories, container, false); final View v = inflater.inflate(R.layout.fragment_my_repositories, container, false);
setHasOptionsMenu(true); setHasOptionsMenu(true);
@ -196,7 +196,7 @@ public class MyRepositoriesFragment extends Fragment {
@Override @Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext())); boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
inflater.inflate(R.menu.search_menu, menu); inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);

View File

@ -3,17 +3,16 @@ package org.mian.gitnex.fragments;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import retrofit2.Call;
import retrofit2.Callback;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
@ -21,6 +20,8 @@ import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.Organization; import org.mian.gitnex.models.Organization;
import org.mian.gitnex.util.TinyDB; import org.mian.gitnex.util.TinyDB;
import retrofit2.Call;
import retrofit2.Callback;
/** /**
* Author M M Arif * Author M M Arif
@ -37,6 +38,7 @@ public class OrganizationInfoFragment extends Fragment {
private TextView orgDescInfo; private TextView orgDescInfo;
private TextView orgWebsiteInfo; private TextView orgWebsiteInfo;
private TextView orgLocationInfo; private TextView orgLocationInfo;
private LinearLayout orgInfoLayout;
private RepoInfoFragment.OnFragmentInteractionListener mListener; private RepoInfoFragment.OnFragmentInteractionListener mListener;
@ -76,6 +78,7 @@ public class OrganizationInfoFragment extends Fragment {
orgDescInfo = v.findViewById(R.id.orgDescInfo); orgDescInfo = v.findViewById(R.id.orgDescInfo);
orgWebsiteInfo = v.findViewById(R.id.orgWebsiteInfo); orgWebsiteInfo = v.findViewById(R.id.orgWebsiteInfo);
orgLocationInfo = v.findViewById(R.id.orgLocationInfo); orgLocationInfo = v.findViewById(R.id.orgLocationInfo);
orgInfoLayout = v.findViewById(R.id.orgInfoLayout);
orgNameInfo.setText(orgName); orgNameInfo.setText(orgName);
@ -99,19 +102,46 @@ public class OrganizationInfoFragment extends Fragment {
Organization orgInfo = response.body(); Organization orgInfo = response.body();
if (response.isSuccessful()) { if (response.code() == 200) {
if (response.code() == 200) { orgInfoLayout.setVisibility(View.VISIBLE);
assert orgInfo != null; assert orgInfo != null;
PicassoService.getInstance(ctx).get().load(orgInfo.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(orgAvatar);
orgDescInfo.setText(orgInfo.getDescription());
orgWebsiteInfo.setText(orgInfo.getWebsite());
orgLocationInfo.setText(orgInfo.getLocation());
mProgressBar.setVisibility(View.GONE); PicassoService.getInstance(ctx).get()
.load(orgInfo.getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(8, 0))
.resize(230, 230)
.centerCrop().into(orgAvatar);
if(!orgInfo.getDescription().isEmpty()) {
orgDescInfo.setText(orgInfo.getDescription());
}
else {
orgDescInfo.setText(getString(R.string.noDataDescription));
}
if(!orgInfo.getWebsite().isEmpty()) {
orgWebsiteInfo.setText(orgInfo.getWebsite());
} }
else {
orgWebsiteInfo.setText(getString(R.string.noDataWebsite));
}
if(!orgInfo.getLocation().isEmpty()) {
orgLocationInfo.setText(orgInfo.getLocation());
}
else {
orgLocationInfo.setText(getString(R.string.noDataLocation));
}
mProgressBar.setVisibility(View.GONE);
}
else if(response.code() == 404) {
mProgressBar.setVisibility(View.GONE);
} }
else { else {

View File

@ -52,7 +52,7 @@ public class OrganizationsFragment extends Fragment {
final View v = inflater.inflate(R.layout.fragment_organizations, container, false); final View v = inflater.inflate(R.layout.fragment_organizations, container, false);
setHasOptionsMenu(true); setHasOptionsMenu(true);
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext())); boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
TinyDB tinyDb = new TinyDB(getContext()); TinyDB tinyDb = new TinyDB(getContext());
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
@ -158,7 +158,7 @@ public class OrganizationsFragment extends Fragment {
@Override @Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext())); boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
inflater.inflate(R.menu.search_menu, menu); inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);

View File

@ -1,14 +1,9 @@
package org.mian.gitnex.fragments; package org.mian.gitnex.fragments;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
@ -17,13 +12,25 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.widget.ImageViewCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayout;
import com.squareup.picasso.Callback;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.MainActivity; import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.util.TinyDB; import org.mian.gitnex.util.TinyDB;
import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import eightbitlab.com.blurview.BlurView;
import eightbitlab.com.blurview.RenderScriptBlur;
/** /**
* Author M M Arif * Author M M Arif
@ -31,26 +38,80 @@ import java.util.Objects;
public class ProfileFragment extends Fragment { public class ProfileFragment extends Fragment {
private Context ctx = getContext(); private Context ctx;
@Nullable @Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
ctx = getContext();
View v = inflater.inflate(R.layout.fragment_profile, container, false); View v = inflater.inflate(R.layout.fragment_profile, container, false);
setHasOptionsMenu(true); setHasOptionsMenu(true);
TinyDB tinyDb = new TinyDB(getContext()); TinyDB tinyDb = new TinyDB(getContext());
BlurView blurView = v.findViewById(R.id.blurView);
TextView userFullName = v.findViewById(R.id.userFullName); TextView userFullName = v.findViewById(R.id.userFullName);
ImageView userAvatarBackground = v.findViewById(R.id.userAvatarBackground);
ImageView userAvatar = v.findViewById(R.id.userAvatar); ImageView userAvatar = v.findViewById(R.id.userAvatar);
TextView userLogin = v.findViewById(R.id.userLogin); TextView userLogin = v.findViewById(R.id.userLogin);
TextView userEmail = v.findViewById(R.id.userEmail); View divider = v.findViewById(R.id.divider);
TextView userLanguage = v.findViewById(R.id.userLanguage);
ImageView userLanguageIcon = v.findViewById(R.id.userLanguageIcon);
ViewGroup aboutFrame = v.findViewById(R.id.aboutFrame);
String[] userLanguageCodes = tinyDb.getString("userLang").split("-");
if(userLanguageCodes.length >= 2) {
Locale locale = new Locale(userLanguageCodes[0], userLanguageCodes[1]);
userLanguage.setText(locale.getDisplayCountry());
}
else {
userLanguage.setText(R.string.notSupported);
}
userFullName.setText(tinyDb.getString("userFullname"));
userLogin.setText(getString(R.string.usernameWithAt, tinyDb.getString("userLogin")));
PicassoService.getInstance(ctx).get()
.load(tinyDb.getString("userAvatar"))
.transform(new RoundedTransformation(8, 0))
.placeholder(R.drawable.loader_animated)
.resize(120, 120)
.centerCrop().into(userAvatar);
PicassoService.getInstance(ctx).get()
.load(tinyDb.getString("userAvatar"))
.into(userAvatarBackground, new Callback() {
@Override
public void onSuccess() {
int invertedColor = new ColorInverter().getImageViewContrastColor(userAvatarBackground);
userFullName.setTextColor(invertedColor);
divider.setBackgroundColor(invertedColor);
userLogin.setTextColor(invertedColor);
userLanguage.setTextColor(invertedColor);
ImageViewCompat.setImageTintList(userLanguageIcon, ColorStateList.valueOf(invertedColor));
blurView.setupWith(aboutFrame)
.setBlurAlgorithm(new RenderScriptBlur(ctx))
.setBlurRadius(3)
.setHasFixedTransformationMatrix(true);
}
@Override
public void onError(Exception e) {}
});
userFullName.setText(tinyDb.getString("userFullname"));
PicassoService.getInstance(ctx).get().load(tinyDb.getString("userAvatar")).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(userAvatar);
userLogin.setText(getString(R.string.usernameWithAt, tinyDb.getString("userLogin")));
userEmail.setText(tinyDb.getString("userEmail"));
ProfileFragment.SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager()); ProfileFragment.SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
@ -79,11 +140,16 @@ public class ProfileFragment extends Fragment {
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0); ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = vg.getChildCount(); int tabsCount = vg.getChildCount();
for (int j = 0; j < tabsCount; j++) { for (int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j); ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
int tabChildCount = vgTab.getChildCount(); int tabChildCount = vgTab.getChildCount();
for (int i = 0; i < tabChildCount; i++) { for (int i = 0; i < tabChildCount; i++) {
View tabViewChild = vgTab.getChildAt(i); View tabViewChild = vgTab.getChildAt(i);
if (tabViewChild instanceof TextView) { if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(myTypeface); ((TextView) tabViewChild).setTypeface(myTypeface);
} }
@ -108,15 +174,22 @@ public class ProfileFragment extends Fragment {
public Fragment getItem(int position) { public Fragment getItem(int position) {
Fragment fragment = null; Fragment fragment = null;
switch (position) { switch (position) {
case 0: // followers case 0: // followers
return ProfileFollowersFragment.newInstance("repoOwner", "repoName"); return ProfileFollowersFragment.newInstance("repoOwner", "repoName");
case 1: // following case 1: // following
return ProfileFollowingFragment.newInstance("repoOwner", "repoName"); return ProfileFollowingFragment.newInstance("repoOwner", "repoName");
case 2: // emails case 2: // emails
return ProfileEmailsFragment.newInstance("repoOwner", "repoName"); return ProfileEmailsFragment.newInstance("repoOwner", "repoName");
} }
return fragment; return fragment;
} }
@Override @Override
@ -128,9 +201,11 @@ public class ProfileFragment extends Fragment {
@Override @Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
menu.clear(); menu.clear();
Objects.requireNonNull(getActivity()).getMenuInflater().inflate(R.menu.profile_dotted_menu, menu); Objects.requireNonNull(getActivity()).getMenuInflater().inflate(R.menu.profile_dotted_menu, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
} }
@Override @Override
@ -139,17 +214,20 @@ public class ProfileFragment extends Fragment {
int id = item.getItemId(); int id = item.getItemId();
switch (id) { switch (id) {
case android.R.id.home: case android.R.id.home:
((MainActivity)ctx).finish(); ((MainActivity)ctx).finish();
return true; return true;
case R.id.profileMenu: case R.id.profileMenu:
BottomSheetProfileFragment bottomSheet = new BottomSheetProfileFragment(); BottomSheetProfileFragment bottomSheet = new BottomSheetProfileFragment();
bottomSheet.show(getChildFragmentManager(), "profileBottomSheet"); bottomSheet.show(getChildFragmentManager(), "profileBottomSheet");
return true; return true;
default: default:
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
}
}
} }
} }

View File

@ -332,6 +332,9 @@ public class PullRequestsFragment extends Fragment {
List<PullRequests> arr = new ArrayList<>(); List<PullRequests> arr = new ArrayList<>();
for(PullRequests d : prList) { for(PullRequests d : prList) {
if(d == null || d.getTitle() == null || d.getBody() == null) {
continue;
}
if(d.getTitle().toLowerCase().contains(text) || d.getBody().toLowerCase().contains(text)) { if(d.getTitle().toLowerCase().contains(text) || d.getBody().toLowerCase().contains(text)) {
arr.add(d); arr.add(d);
} }

View File

@ -4,10 +4,34 @@ import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.Spanned;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
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.ClickListener;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.Objects;
import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon; import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin; import io.noties.markwon.core.CorePlugin;
@ -26,30 +50,6 @@ import io.noties.markwon.image.svg.SvgMediaDecoder;
import io.noties.markwon.linkify.LinkifyPlugin; import io.noties.markwon.linkify.LinkifyPlugin;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import android.text.Spanned;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
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.ClickListener;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.Objects;
/** /**
* Author M M Arif * Author M M Arif
@ -57,405 +57,427 @@ import java.util.Objects;
public class RepoInfoFragment extends Fragment { public class RepoInfoFragment extends Fragment {
private Context ctx; private Context ctx;
private ProgressBar mProgressBar; private ProgressBar mProgressBar;
private LinearLayout pageContent; private LinearLayout pageContent;
private static String repoNameF = "param2"; private static String repoNameF = "param2";
private static String repoOwnerF = "param1"; private static String repoOwnerF = "param1";
private String repoName; private String repoName;
private String repoOwner; private String repoOwner;
private TextView repoMetaName; private TextView repoMetaName;
private TextView repoMetaDescription; private TextView repoMetaDescription;
private TextView repoMetaStars; private TextView repoMetaStars;
private TextView repoMetaPullRequests; private TextView repoMetaPullRequests;
private LinearLayout repoMetaPullRequestsFrame; private LinearLayout repoMetaPullRequestsFrame;
private TextView repoMetaForks; private TextView repoMetaForks;
private TextView repoMetaSize; private TextView repoMetaSize;
private TextView repoMetaWatchers; private TextView repoMetaWatchers;
private TextView repoMetaCreatedAt; private TextView repoMetaCreatedAt;
private TextView repoMetaWebsite; private TextView repoMetaWebsite;
private Button repoAdditionalButton; private Button repoAdditionalButton;
private TextView repoFileContents; private TextView repoFileContents;
private LinearLayout repoMetaFrame; private LinearLayout repoMetaFrame;
private ImageView repoMetaDataExpandCollapse; private ImageView repoMetaDataExpandCollapse;
private ImageView repoFilenameExpandCollapse; private ImageView repoFilenameExpandCollapse;
private LinearLayout fileContentsFrameHeader; private LinearLayout fileContentsFrameHeader;
private LinearLayout fileContentsFrame; private LinearLayout fileContentsFrame;
private OnFragmentInteractionListener mListener; private OnFragmentInteractionListener mListener;
public RepoInfoFragment() { public RepoInfoFragment() {
} }
public static RepoInfoFragment newInstance(String param1, String param2) { public static RepoInfoFragment newInstance(String param1, String param2) {
RepoInfoFragment fragment = new RepoInfoFragment(); RepoInfoFragment fragment = new RepoInfoFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(repoOwnerF, param1); args.putString(repoOwnerF, param1);
args.putString(repoNameF, param2); args.putString(repoNameF, param2);
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (getArguments() != null) { if (getArguments() != null) {
repoName = getArguments().getString(repoNameF); repoName = getArguments().getString(repoNameF);
repoOwner = getArguments().getString(repoOwnerF); repoOwner = getArguments().getString(repoOwnerF);
} }
} }
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_repo_info, container, false); View v = inflater.inflate(R.layout.fragment_repo_info, container, false);
TinyDB tinyDb = new TinyDB(getContext()); TinyDB tinyDb = new TinyDB(getContext());
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid"); final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final String locale = tinyDb.getString("locale"); final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat"); final String timeFormat = tinyDb.getString("dateFormat");
ctx = getActivity(); ctx = getActivity();
pageContent = v.findViewById(R.id.repoInfoLayout); pageContent = v.findViewById(R.id.repoInfoLayout);
pageContent.setVisibility(View.GONE); pageContent.setVisibility(View.GONE);
mProgressBar = v.findViewById(R.id.progress_bar); mProgressBar = v.findViewById(R.id.progress_bar);
repoMetaName = v.findViewById(R.id.repoMetaName); repoMetaName = v.findViewById(R.id.repoMetaName);
repoMetaDescription = v.findViewById(R.id.repoMetaDescription); repoMetaDescription = v.findViewById(R.id.repoMetaDescription);
repoMetaStars = v.findViewById(R.id.repoMetaStars); repoMetaStars = v.findViewById(R.id.repoMetaStars);
repoMetaPullRequests = v.findViewById(R.id.repoMetaPullRequests); repoMetaPullRequests = v.findViewById(R.id.repoMetaPullRequests);
repoMetaPullRequestsFrame = v.findViewById(R.id.repoMetaPullRequestsFrame); repoMetaPullRequestsFrame = v.findViewById(R.id.repoMetaPullRequestsFrame);
repoMetaForks = v.findViewById(R.id.repoMetaForks); repoMetaForks = v.findViewById(R.id.repoMetaForks);
repoMetaSize = v.findViewById(R.id.repoMetaSize); repoMetaSize = v.findViewById(R.id.repoMetaSize);
repoMetaWatchers = v.findViewById(R.id.repoMetaWatchers); repoMetaWatchers = v.findViewById(R.id.repoMetaWatchers);
repoMetaCreatedAt = v.findViewById(R.id.repoMetaCreatedAt); repoMetaCreatedAt = v.findViewById(R.id.repoMetaCreatedAt);
repoMetaWebsite = v.findViewById(R.id.repoMetaWebsite); repoMetaWebsite = v.findViewById(R.id.repoMetaWebsite);
repoAdditionalButton = v.findViewById(R.id.repoAdditionalButton); repoAdditionalButton = v.findViewById(R.id.repoAdditionalButton);
repoFileContents = v.findViewById(R.id.repoFileContents); repoFileContents = v.findViewById(R.id.repoFileContents);
repoMetaFrame = v.findViewById(R.id.repoMetaFrame); repoMetaFrame = v.findViewById(R.id.repoMetaFrame);
LinearLayout repoMetaFrameHeader = v.findViewById(R.id.repoMetaFrameHeader); LinearLayout repoMetaFrameHeader = v.findViewById(R.id.repoMetaFrameHeader);
repoMetaDataExpandCollapse = v.findViewById(R.id.repoMetaDataExpandCollapse); repoMetaDataExpandCollapse = v.findViewById(R.id.repoMetaDataExpandCollapse);
repoFilenameExpandCollapse = v.findViewById(R.id.repoFilenameExpandCollapse); repoFilenameExpandCollapse = v.findViewById(R.id.repoFilenameExpandCollapse);
fileContentsFrameHeader = v.findViewById(R.id.fileContentsFrameHeader); fileContentsFrameHeader = v.findViewById(R.id.fileContentsFrameHeader);
fileContentsFrame = v.findViewById(R.id.fileContentsFrame); fileContentsFrame = v.findViewById(R.id.fileContentsFrame);
repoMetaFrame.setVisibility(View.GONE); repoMetaFrame.setVisibility(View.GONE);
getRepoInfo(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, locale, timeFormat); getRepoInfo(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, locale, timeFormat);
getFileContents(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, getResources().getString(R.string.defaultFilename)); getFileContents(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, getResources().getString(R.string.defaultFilename));
if(isExpandViewVisible()) { if(isExpandViewVisible()) {
toggleExpandView(); toggleExpandView();
} }
if(!isExpandViewMetaVisible()) { if(!isExpandViewMetaVisible()) {
toggleExpandViewMeta(); toggleExpandViewMeta();
} }
fileContentsFrameHeader.setOnClickListener(new View.OnClickListener() { fileContentsFrameHeader.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
toggleExpandView(); toggleExpandView();
} }
}); });
repoMetaFrameHeader.setOnClickListener(new View.OnClickListener() { repoMetaFrameHeader.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
toggleExpandViewMeta(); toggleExpandViewMeta();
} }
}); });
return v; return v;
} }
public void onButtonPressed(Uri uri) { public void onButtonPressed(Uri uri) {
if (mListener != null) { if (mListener != null) {
mListener.onFragmentInteraction(uri); mListener.onFragmentInteraction(uri);
} }
} }
@Override @Override
public void onDetach() { public void onDetach() {
super.onDetach(); super.onDetach();
mListener = null; mListener = null;
} }
public interface OnFragmentInteractionListener { public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri); void onFragmentInteraction(Uri uri);
} }
private void toggleExpandView() { private void toggleExpandView() {
if (repoFileContents.getVisibility() == View.GONE) { if (repoFileContents.getVisibility() == View.GONE) {
repoFilenameExpandCollapse.setImageResource(R.drawable.ic_arrow_up); repoFilenameExpandCollapse.setImageResource(R.drawable.ic_arrow_up);
repoFileContents.setVisibility(View.VISIBLE); repoFileContents.setVisibility(View.VISIBLE);
//Animation slide_down = AnimationUtils.loadAnimation(getContext(), R.anim.slide_down); //Animation slide_down = AnimationUtils.loadAnimation(getContext(), R.anim.slide_down);
//fileContentsFrame.startAnimation(slide_down); //fileContentsFrame.startAnimation(slide_down);
} }
else { else {
repoFilenameExpandCollapse.setImageResource(R.drawable.ic_arrow_down); repoFilenameExpandCollapse.setImageResource(R.drawable.ic_arrow_down);
repoFileContents.setVisibility(View.GONE); repoFileContents.setVisibility(View.GONE);
//Animation slide_up = AnimationUtils.loadAnimation(getContext(), R.anim.slide_up); //Animation slide_up = AnimationUtils.loadAnimation(getContext(), R.anim.slide_up);
//fileContentsFrame.startAnimation(slide_up); //fileContentsFrame.startAnimation(slide_up);
} }
} }
private boolean isExpandViewVisible() { private boolean isExpandViewVisible() {
return repoFileContents.getVisibility() == View.VISIBLE; return repoFileContents.getVisibility() == View.VISIBLE;
} }
private void toggleExpandViewMeta() { private void toggleExpandViewMeta() {
if (repoMetaFrame.getVisibility() == View.GONE) { if (repoMetaFrame.getVisibility() == View.GONE) {
repoMetaDataExpandCollapse.setImageResource(R.drawable.ic_arrow_up); repoMetaDataExpandCollapse.setImageResource(R.drawable.ic_arrow_up);
repoMetaFrame.setVisibility(View.VISIBLE); repoMetaFrame.setVisibility(View.VISIBLE);
//Animation slide_down = AnimationUtils.loadAnimation(getContext(), R.anim.slide_down); //Animation slide_down = AnimationUtils.loadAnimation(getContext(), R.anim.slide_down);
//repoMetaFrame.startAnimation(slide_down); //repoMetaFrame.startAnimation(slide_down);
} }
else { else {
repoMetaDataExpandCollapse.setImageResource(R.drawable.ic_arrow_down); repoMetaDataExpandCollapse.setImageResource(R.drawable.ic_arrow_down);
repoMetaFrame.setVisibility(View.GONE); repoMetaFrame.setVisibility(View.GONE);
//Animation slide_up = AnimationUtils.loadAnimation(getContext(), R.anim.slide_up); //Animation slide_up = AnimationUtils.loadAnimation(getContext(), R.anim.slide_up);
//repoMetaFrame.startAnimation(slide_up); //repoMetaFrame.startAnimation(slide_up);
} }
} }
private boolean isExpandViewMetaVisible() { private boolean isExpandViewMetaVisible() {
return repoMetaFrame.getVisibility() == View.VISIBLE; return repoMetaFrame.getVisibility() == View.VISIBLE;
} }
private void getRepoInfo(String instanceUrl, String token, final String owner, String repo, final String locale, final String timeFormat) { private void getRepoInfo(String instanceUrl, String token, final String owner, String repo, final String locale, final String timeFormat) {
final TinyDB tinyDb = new TinyDB(getContext()); final TinyDB tinyDb = new TinyDB(getContext());
Call<UserRepositories> call = RetrofitClient Call<UserRepositories> call = RetrofitClient
.getInstance(instanceUrl, getContext()) .getInstance(instanceUrl, getContext())
.getApiInterface() .getApiInterface()
.getUserRepository(token, owner, repo); .getUserRepository(token, owner, repo);
call.enqueue(new Callback<UserRepositories>() { call.enqueue(new Callback<UserRepositories>() {
@Override @Override
public void onResponse(@NonNull Call<UserRepositories> call, @NonNull retrofit2.Response<UserRepositories> response) { public void onResponse(@NonNull Call<UserRepositories> call, @NonNull retrofit2.Response<UserRepositories> response) {
UserRepositories repoInfo = response.body(); UserRepositories repoInfo = response.body();
if (isAdded()) { if (isAdded()) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
if (response.code() == 200) { if (response.code() == 200) {
assert repoInfo != null; assert repoInfo != null;
repoMetaName.setText(repoInfo.getName()); repoMetaName.setText(repoInfo.getName());
repoMetaDescription.setText(repoInfo.getDescription());
repoMetaStars.setText(repoInfo.getStars_count());
if(repoInfo.getOpen_pull_count() != null) { if(!repoInfo.getDescription().isEmpty()) {
repoMetaPullRequests.setText(repoInfo.getOpen_pull_count()); repoMetaDescription.setText(repoInfo.getDescription());
} }
else { else {
repoMetaPullRequestsFrame.setVisibility(View.GONE); repoMetaDescription.setText(getString(R.string.noDataDescription));
} }
repoMetaForks.setText(repoInfo.getForks_count()); repoMetaStars.setText(repoInfo.getStars_count());
repoMetaWatchers.setText(repoInfo.getWatchers_count());
if(repoInfo.getSize() != 0) { if(repoInfo.getOpen_pull_count() != null) {
repoMetaSize.setText(AppUtil.formatFileSize(repoInfo.getSize())); repoMetaPullRequests.setText(repoInfo.getOpen_pull_count());
} }
else { else {
repoMetaSize.setText("0"); repoMetaPullRequestsFrame.setVisibility(View.GONE);
} }
repoMetaCreatedAt.setText(TimeHelper.formatTime(repoInfo.getCreated_at(), new Locale(locale), timeFormat, ctx)); repoMetaForks.setText(repoInfo.getForks_count());
if(timeFormat.equals("pretty")) { repoMetaWatchers.setText(repoInfo.getWatchers_count());
repoMetaCreatedAt.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(repoInfo.getCreated_at()), ctx));
}
String repoMetaUpdatedAt = TimeHelper.formatTime(repoInfo.getUpdated_at(), new Locale(locale), timeFormat, ctx); if(repoInfo.getSize() != 0) {
repoMetaSize.setText(AppUtil.formatFileSize(repoInfo.getSize()));
}
else {
repoMetaSize.setText("0 B");
}
String website = (repoInfo.getWebsite().isEmpty()) ? getResources().getString(R.string.noDataWebsite) : repoInfo.getWebsite(); repoMetaCreatedAt.setText(TimeHelper.formatTime(repoInfo.getCreated_at(), new Locale(locale), timeFormat, ctx));
repoMetaWebsite.setText(website); if(timeFormat.equals("pretty")) {
repoMetaCreatedAt.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(repoInfo.getCreated_at()), ctx));
}
repoAdditionalButton.setOnClickListener(v -> { String repoMetaUpdatedAt = TimeHelper.formatTime(repoInfo.getUpdated_at(), new Locale(locale), timeFormat, ctx);
StringBuilder message = new StringBuilder(); String website = (repoInfo.getWebsite().isEmpty()) ? getResources().getString(R.string.noDataWebsite) : repoInfo.getWebsite();
repoMetaWebsite.setText(website);
message.append(getResources().getString(R.string.infoTabRepoDefaultBranch)) repoAdditionalButton.setOnClickListener(v -> {
.append(" :\n").append(repoInfo.getDefault_branch()).append("\n\n");
message.append(getResources().getString(R.string.infoTabRepoUpdatedAt)) View view = LayoutInflater.from(ctx).inflate(R.layout.layout_repo_more_info, null);
.append(" :\n").append(repoMetaUpdatedAt).append("\n\n");
message.append(getResources().getString(R.string.infoTabRepoSshUrl)) TextView defaultBranchHeader = view.findViewById(R.id.defaultBranchHeader);
.append(" :\n").append(repoInfo.getSsh_url()).append("\n\n"); TextView defaultBranchContent = view.findViewById(R.id.defaultBranchContent);
message.append(getResources().getString(R.string.infoTabRepoCloneUrl)) TextView lastUpdatedHeader = view.findViewById(R.id.lastUpdatedHeader);
.append(" :\n").append(repoInfo.getClone_url()).append("\n\n"); TextView lastUpdatedContent = view.findViewById(R.id.lastUpdatedContent);
message.append(getResources().getString(R.string.infoTabRepoRepoUrl)) TextView sshUrlHeader = view.findViewById(R.id.sshUrlHeader);
.append(" :\n").append(repoInfo.getHtml_url()); TextView sshUrlContent = view.findViewById(R.id.sshUrlContent);
AlertDialog.Builder alertDialog = new AlertDialog.Builder(ctx); TextView cloneUrlHeader = view.findViewById(R.id.cloneUrlHeader);
TextView cloneUrlContent = view.findViewById(R.id.cloneUrlContent);
alertDialog.setTitle(getResources().getString(R.string.infoMoreInformation)); TextView repoUrlHeader = view.findViewById(R.id.repoUrlHeader);
alertDialog.setMessage(message); TextView repoUrlContent = view.findViewById(R.id.repoUrlContent);
alertDialog.setPositiveButton(getResources().getString(R.string.close), (dialog, which) -> dialog.dismiss());
alertDialog.create().show();
}); defaultBranchHeader.setText(getString(R.string.infoTabRepoDefaultBranch));
defaultBranchContent.setText(repoInfo.getDefault_branch());
if(repoInfo.getHas_issues() != null) { lastUpdatedHeader.setText(getString(R.string.infoTabRepoUpdatedAt));
tinyDb.putBoolean("hasIssues", repoInfo.getHas_issues()); lastUpdatedContent.setText(repoMetaUpdatedAt);
}
else {
tinyDb.putBoolean("hasIssues", true);
}
tinyDb.putString("repoHtmlUrl", repoInfo.getHtml_url()); sshUrlHeader.setText(getString(R.string.infoTabRepoSshUrl));
sshUrlContent.setText(repoInfo.getSsh_url());
mProgressBar.setVisibility(View.GONE); cloneUrlHeader.setText(getString(R.string.infoTabRepoCloneUrl));
pageContent.setVisibility(View.VISIBLE); cloneUrlContent.setText(repoInfo.getClone_url());
} repoUrlHeader.setText(getString(R.string.infoTabRepoRepoUrl));
repoUrlContent.setText(repoInfo.getHtml_url());
} AlertDialog.Builder alertDialog = new AlertDialog.Builder(ctx);
else {
Log.e("onFailure", String.valueOf(response.code()));
}
} alertDialog.setTitle(getResources().getString(R.string.infoMoreInformation));
alertDialog.setView(view);
alertDialog.setPositiveButton(getResources().getString(R.string.close), (dialog, which) -> dialog.dismiss());
alertDialog.create().show();
} });
@Override if(repoInfo.getHas_issues() != null) {
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) { tinyDb.putBoolean("hasIssues", repoInfo.getHas_issues());
Log.e("onFailure", t.toString()); }
} else {
}); tinyDb.putBoolean("hasIssues", true);
}
} tinyDb.putString("repoHtmlUrl", repoInfo.getHtml_url());
private void getFileContents(String instanceUrl, String token, final String owner, String repo, final String filename) { mProgressBar.setVisibility(View.GONE);
pageContent.setVisibility(View.VISIBLE);
final TinyDB tinyDb = new TinyDB(getContext()); }
Call<String> call = RetrofitClient }
.getInstance(instanceUrl, getContext()) else {
.getApiInterface() Log.e("onFailure", String.valueOf(response.code()));
.getFileContents(token, owner, repo, filename); }
call.enqueue(new Callback<String>() { }
@Override }
public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) {
if (isAdded()) { @Override
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
if (response.code() == 200) { }
final Markwon markwon = Markwon.builder(Objects.requireNonNull(getContext())) private void getFileContents(String instanceUrl, String token, final String owner, String repo, final String filename) {
.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 = getContext().getResources().getIdentifier( final TinyDB tinyDb = new TinyDB(getContext());
raw.substring("drawable://".length()),
"drawable",
getContext().getPackageName());
final Drawable drawable = getContext().getDrawable(resourceId); Call<String> call = RetrofitClient
.getInstance(instanceUrl, getContext())
.getApiInterface()
.getFileContents(token, owner, repo, filename);
assert drawable != null; call.enqueue(new Callback<String>() {
return ImageItem.withResult(drawable);
}
@NonNull @Override
@Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) {
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
@Nullable
@Override
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
return null;
}
});
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(getContext().getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(getContext().getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder
.codeTextColor(tinyDb.getInt("codeBlockColor"))
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(getContext()))
.usePlugin(TaskListPlugin.create(getContext()))
.usePlugin(HtmlPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
Spanned bodyWithMD = null; if (isAdded()) {
if (response.body() != null) { if (response.code() == 200) {
bodyWithMD = markwon.toMarkdown(response.body());
}
assert bodyWithMD != null; final Markwon markwon = Markwon.builder(Objects.requireNonNull(getContext()))
markwon.setParsedMarkdown(repoFileContents, bodyWithMD); .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) {
} else if (response.code() == 401) { final int resourceId = getContext().getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
getContext().getPackageName());
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), final Drawable drawable = getContext().getDrawable(resourceId);
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
} else if (response.code() == 403) { assert drawable != null;
return ImageItem.withResult(drawable);
}
Toasty.info(ctx, ctx.getString(R.string.authorizeError)); @NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
@Nullable
@Override
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
return null;
}
});
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(getContext().getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(getContext().getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder
.codeTextColor(tinyDb.getInt("codeBlockColor"))
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(getContext()))
.usePlugin(TaskListPlugin.create(getContext()))
.usePlugin(HtmlPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
} else if (response.code() == 404) { Spanned bodyWithMD = null;
fileContentsFrameHeader.setVisibility(View.GONE); if (response.body() != null) {
fileContentsFrame.setVisibility(View.GONE); bodyWithMD = markwon.toMarkdown(response.body());
}
} else { assert bodyWithMD != null;
markwon.setParsedMarkdown(repoFileContents, bodyWithMD);
Toasty.info(getContext(), getString(R.string.genericError)); } 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) {
@Override Toasty.info(ctx, ctx.getString(R.string.authorizeError));
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
} } else if (response.code() == 404) {
fileContentsFrameHeader.setVisibility(View.GONE);
fileContentsFrame.setVisibility(View.GONE);
} else {
Toasty.info(getContext(), getString(R.string.genericError));
}
}
}
@Override
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
} }

View File

@ -152,7 +152,7 @@ public class RepositoriesByOrgFragment extends Fragment {
@Override @Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext())); boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
inflater.inflate(R.menu.search_menu, menu); inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);

View File

@ -51,7 +51,7 @@ public class RepositoriesFragment extends Fragment {
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext())); boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
final View v = inflater.inflate(R.layout.fragment_repositories, container, false); final View v = inflater.inflate(R.layout.fragment_repositories, container, false);
setHasOptionsMenu(true); setHasOptionsMenu(true);
@ -161,7 +161,7 @@ public class RepositoriesFragment extends Fragment {
@Override @Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext())); boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
inflater.inflate(R.menu.search_menu, menu); inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);

View File

@ -78,7 +78,7 @@ public class StarredRepositoriesFragment extends Fragment {
Bundle savedInstanceState) { Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_starred_repositories, container, false); View v = inflater.inflate(R.layout.fragment_starred_repositories, container, false);
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext())); boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
setHasOptionsMenu(true); setHasOptionsMenu(true);
TinyDB tinyDb = new TinyDB(getContext()); TinyDB tinyDb = new TinyDB(getContext());
@ -186,7 +186,7 @@ public class StarredRepositoriesFragment extends Fragment {
@Override @Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext())); boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
inflater.inflate(R.menu.search_menu, menu); inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);

View File

@ -148,7 +148,7 @@ public class TeamsByOrgFragment extends Fragment {
@Override @Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext())); boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
inflater.inflate(R.menu.search_menu, menu); inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);

View File

@ -19,28 +19,26 @@ public class AlertDialogs {
public static void authorizationTokenRevokedDialog(final Context context, String title, String message, String copyNegativeButton, String copyPositiveButton) { public static void authorizationTokenRevokedDialog(final Context context, String title, String message, String copyNegativeButton, String copyPositiveButton) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context)
.setTitle(title)
.setMessage(message)
.setCancelable(true)
.setIcon(R.drawable.ic_warning)
.setNegativeButton(copyNegativeButton, (dialog, which) -> dialog.dismiss())
.setPositiveButton(copyPositiveButton, (dialog, which) -> {
alertDialogBuilder final TinyDB tinyDb = new TinyDB(context);
.setTitle(title) tinyDb.putBoolean("loggedInMode", false);
.setMessage(message) tinyDb.remove("basicAuthPassword");
.setCancelable(true) tinyDb.putBoolean("basicAuthFlag", false);
.setIcon(R.drawable.ic_warning) Intent intent = new Intent(context, LoginActivity.class);
.setNegativeButton(copyNegativeButton, (dialog, which) -> dialog.dismiss()) context.startActivity(intent);
.setPositiveButton(copyPositiveButton, (dialog, which) -> { dialog.dismiss();
final TinyDB tinyDb = new TinyDB(context); });
tinyDb.putBoolean("loggedInMode", false);
tinyDb.remove("basicAuthPassword");
tinyDb.putBoolean("basicAuthFlag", false);
Intent intent = new Intent(context, LoginActivity.class);
context.startActivity(intent);
dialog.dismiss();
}); alertDialogBuilder.create().show();
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
} }
public static void labelDeleteDialog(final Context context, final String labelTitle, final String labelId, String title, String message, String positiveButton, String negativeButton) { public static void labelDeleteDialog(final Context context, final String labelTitle, final String labelId, String title, String message, String positiveButton, String negativeButton) {

View File

@ -1,6 +1,9 @@
package org.mian.gitnex.helpers; package org.mian.gitnex.helpers;
import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.widget.ImageView;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
/** /**
@ -16,7 +19,7 @@ public class ColorInverter {
int d; int d;
if (a < 0.5) { if (a < 0.5) {
d = 0; // black d = 30; // almost black
} else { } else {
d = 255; // white d = 255; // white
} }
@ -24,4 +27,35 @@ public class ColorInverter {
return Color.rgb(d, d, d); return Color.rgb(d, d, d);
} }
@ColorInt
public int getImageViewContrastColor(ImageView imageView) {
if(imageView != null) {
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
int colorSum = 0;
int divisionValue = 0;
for(int height=0; height<bitmap.getHeight(); height += 10) {
for(int width=0; width<bitmap.getWidth(); width += 10) {
colorSum += bitmap.getPixel(width, height);
divisionValue++;
}
}
// Calculate average color
return getContrastColor(colorSum / divisionValue);
}
else {
return Color.rgb(255, 255, 255);
}
}
} }

View File

@ -23,73 +23,4 @@ public class LabelWidthCalculator {
} }
public static int customWidth(int labelLength) {
int width = 33;
if(labelLength == 20) {
width = ((width * labelLength) - 150);
}
else if(labelLength == 19) {
width = ((width * labelLength) - 140);
}
else if(labelLength == 18) {
width = ((width * labelLength) - 130);
}
else if(labelLength == 17) {
width = ((width * labelLength) - 120);
}
else if(labelLength == 16) {
width = ((width * labelLength) - 110);
}
else if(labelLength == 15) {
width = ((width * labelLength) - 100);
}
else if(labelLength == 14) {
width = ((width * labelLength) - 90);
}
else if(labelLength == 13) {
width = ((width * labelLength) - 80);
}
else if(labelLength == 12) {
width = ((width * labelLength) - 70);
}
else if(labelLength == 11) {
width = ((width * labelLength) - 60);
}
else if(labelLength == 10) {
width = ((width * labelLength) - 50);
}
else if(labelLength == 9) {
width = ((width * labelLength) - 40);
}
else if(labelLength == 8) {
width = ((width * labelLength) - 30);
}
else if(labelLength == 7) {
width = ((width * labelLength) - 20);
}
else if(labelLength == 6) {
width = ((width * labelLength) - 10);
}
else if(labelLength == 5) {
width = ((width * labelLength) - 10);
}
else if(labelLength == 4) {
width = ((width * labelLength) - 10);
}
else if(labelLength == 3) {
width = ((width * labelLength) - 10);
}
else if(labelLength == 2) {
width = ((width * labelLength));
}
else {
width = (width * labelLength - 5);
}
return width;
}
} }

View File

@ -0,0 +1,145 @@
package org.mian.gitnex.helpers;
import org.mian.gitnex.models.FileDiffView;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Author 6543
*/
public class ParseDiff {
private static String[] getFileNames(String raw) {
String[] lines2 = raw.split(" b/");
if(lines2.length < 2) {
return new String[1];
}
String oldName = lines2[0];
String newName = lines2[1].split("\\n")[0];
return new String[]{oldName, newName};
}
private static String getFileInfo(String raw) {
if(raw.contains("\ndeleted file mode \\d+\n")) {
return "delete";
}
else if(raw.contains("\nnew file mode \\d+\n")) {
return "new";
}
return "change";
}
private static int[] countRemoveAdd(String raw) {
int rm = 0, add = 0;
Pattern rmPattern = Pattern.compile("\n-");
Pattern addPattern = Pattern.compile("\n\\+");
Matcher rmMatcher = rmPattern.matcher(raw);
Matcher addMatcher = addPattern.matcher(raw);
while(rmMatcher.find())
rm++;
while(addMatcher.find())
add++;
return new int[]{rm, add};
}
public static List<FileDiffView> getFileDiffViewArray(String raw) {
List<FileDiffView> fileContentsArray = new ArrayList<>();
String[] lines = raw.split("(^|\\n)diff --git a/");
if(lines.length > 1) {
// for each file in diff
for(int i = 1; i < lines.length; i++) {
// check if it is a binary file
if(lines[i].contains("\nBinary files a/")) {
String[] fileNames = getFileNames(lines[i]);
if(fileNames.length != 2) {
continue;
}
fileContentsArray.add(new FileDiffView(fileNames[0], fileNames[1], "binary", "", null));
}
// check if it is a binary patch
else if(lines[i].contains("\nGIT binary patch\n")) {
String[] fileNames = getFileNames(lines[i]);
if(fileNames.length != 2) {
continue;
}
String[] tmp = lines[i].split("literal \\d+\\n");
String rawContent = "";
if(tmp.length >= 2) {
rawContent = tmp[1].replace("\n", "");
}
List<FileDiffView.Content> contents = new ArrayList<>();
contents.add(new FileDiffView.Content(rawContent));
fileContentsArray.add(new FileDiffView(fileNames[0], fileNames[1], "binary", getFileInfo(lines[i]), contents));
}
// check if it is normal diff
else if(lines[i].contains("\n@@ -")) {
String[] fileNames = getFileNames(lines[i]);
if(fileNames.length != 2) {
continue;
}
String[] rawDiffs = lines[i].split("\n@@ -");
if(rawDiffs.length <= 1) {
continue;
}
List<FileDiffView.Content> contents = new ArrayList<>();
// parse each section starting with "@@" at line beginning
for(int j = 1; j < rawDiffs.length; j++) {
// remove stats info (ending with @@)
// raw diff is the whole raw diff without any diff meta info's
String[] rawDiff = rawDiffs[j].split("^\\d+(,\\d+)? \\+\\d+(,\\d+)? @@");
if(rawDiff.length <= 1) {
continue;
}
// extract the diff stats info of the first line
String statsLine = rawDiffs[j].split("\n")[0].split(" @@")[0];
// parse "-1,2 +2,3" and "-1 -3" and so on
int oldStart = 0, newStart = 0;
String diffPos[] = statsLine.split(" \\+");
if(diffPos.length == 2) {
oldStart = Integer.parseInt(diffPos[0].split(",")[0]);
newStart = Integer.parseInt(diffPos[1].split(",")[0]);
}
// get stat
int[] stats = countRemoveAdd(rawDiff[1]);
contents.add(new FileDiffView.Content(rawDiff[1], oldStart, newStart, stats[0], stats[1]));
}
fileContentsArray.add(new FileDiffView(fileNames[0], fileNames[1], "diff", getFileInfo(lines[i]), contents));
}
// a rename
else if(lines[i].contains("\nrename from")) {
String[] lines2 = lines[i].split("\\nrename (from|to )");
if(lines2.length != 3) {
continue;
}
fileContentsArray.add(new FileDiffView(lines2[1], lines2[2].split("\\n")[0], "rename", "rename", null));
}
}
}
return fileContentsArray;
}
}

View File

@ -0,0 +1,37 @@
package org.mian.gitnex.helpers;
/**
* Author opyale
*/
public class PathsHelper {
public static String join(String... paths) {
StringBuilder stringBuilder = new StringBuilder();
for(String path : paths) {
if(path != null && !path.isEmpty()) {
if(!path.startsWith("/")) {
stringBuilder.append("/");
}
if(path.endsWith("/")) {
path = path.substring(0, path.lastIndexOf("/"));
}
stringBuilder.append(path);
}
}
return stringBuilder.append("/").toString();
}
}

View File

@ -17,7 +17,7 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
/** /**
* Author anonTree1417 * Author opyale
*/ */
public class PicassoCache implements Cache { public class PicassoCache implements Cache {

View File

@ -13,34 +13,34 @@ import org.mian.gitnex.R;
public class Toasty { public class Toasty {
public static void info(Context context, String message) { public static void info(Context context, String message) {
LayoutInflater inflater = LayoutInflater.from(context); LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate( context.getResources().getLayout(R.layout.custom_toast), null ); View view = inflater.inflate(context.getResources().getLayout(R.layout.custom_toast), null);
TextView text = view.findViewById(R.id.toastText); TextView text = view.findViewById(R.id.toastText);
text.setText(message); text.setText(message);
Toast toast = new Toast(context); Toast toast = new Toast(context);
toast.setDuration(Toast.LENGTH_LONG); toast.setDuration(Toast.LENGTH_LONG);
toast.setView(view); toast.setView(view);
toast.show(); toast.show();
} }
public static void error(Context context, String message) { public static void error(Context context, String message) {
LayoutInflater inflater = LayoutInflater.from(context); LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate( context.getResources().getLayout(R.layout.custom_toast_error), null ); View view = inflater.inflate(context.getResources().getLayout(R.layout.custom_toast_error), null);
TextView text = view.findViewById(R.id.toastText); TextView text = view.findViewById(R.id.toastText);
text.setText(message); text.setText(message);
Toast toast = new Toast(context); Toast toast = new Toast(context);
toast.setDuration(Toast.LENGTH_LONG); toast.setDuration(Toast.LENGTH_LONG);
toast.setView(view); toast.setView(view);
toast.show(); toast.show();
} }
} }

View File

@ -9,34 +9,39 @@ import java.net.URISyntaxException;
public class UrlHelper { public class UrlHelper {
public static String cleanUrl(String url) { public static String cleanUrl(String url) {
URI uri = null; URI uri = null;
try { try {
uri = new URI(url); uri = new URI(url);
} catch (URISyntaxException e) { }
e.printStackTrace(); catch(URISyntaxException e) {
} e.printStackTrace();
}
assert uri != null; assert uri != null;
String urlProtocol = uri.getScheme(); String urlProtocol = uri.getScheme();
String urlHost = uri.getHost(); String urlHost = uri.getHost();
int urlPort = uri.getPort(); int urlPort = uri.getPort();
String urlFinal = null; String urlFinal = null;
if(urlPort > 0) { if(urlPort > 0) {
urlFinal = urlProtocol + "://" + urlHost + ":" + urlPort; urlFinal = urlProtocol + "://" + urlHost + ":" + urlPort;
} }
else if(urlProtocol != null) { else if(urlProtocol != null) {
urlFinal = urlProtocol + "://" + urlHost; urlFinal = urlProtocol + "://" + urlHost;
} }
else { else {
urlFinal = urlHost; urlFinal = urlHost;
} }
return urlFinal; return urlFinal;
} }
public static String fixScheme(String url, String scheme) {
return !url.matches("^(http|https)://.+$") ? scheme + "://" + url : url;
}
} }

View File

@ -1,6 +1,6 @@
package org.mian.gitnex.helpers; package org.mian.gitnex.helpers;
import org.jetbrains.annotations.NotNull; import androidx.annotation.NonNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -70,7 +70,7 @@ public class Version {
* @param v * @param v
* @return * @return
*/ */
public boolean equal(@NotNull Version v) { public boolean equal(@NonNull Version v) {
int rounds = Math.min(this.values.size(), v.values.size()); int rounds = Math.min(this.values.size(), v.values.size());
for(int i = 0; i < rounds; i++) { for(int i = 0; i < rounds; i++) {
@ -101,7 +101,7 @@ public class Version {
* @param v * @param v
* @return * @return
*/ */
public boolean less(@NotNull Version v) { public boolean less(@NonNull Version v) {
int rounds = Math.min(this.values.size(), v.values.size()); int rounds = Math.min(this.values.size(), v.values.size());
for(int i = 0; i < rounds; i++) { for(int i = 0; i < rounds; i++) {
@ -142,7 +142,7 @@ public class Version {
* @param v * @param v
* @return * @return
*/ */
public boolean higher(@NotNull Version v) { public boolean higher(@NonNull Version v) {
int rounds = Math.min(this.values.size(), v.values.size()); int rounds = Math.min(this.values.size(), v.values.size());
for(int i = 0; i < rounds; i++) { for(int i = 0; i < rounds; i++) {
@ -182,7 +182,7 @@ public class Version {
* @param v * @param v
* @return * @return
*/ */
public boolean lessOrEqual(@NotNull Version v) { public boolean lessOrEqual(@NonNull Version v) {
int rounds = Math.min(this.values.size(), v.values.size()); int rounds = Math.min(this.values.size(), v.values.size());
for(int i = 0; i < rounds; i++) { for(int i = 0; i < rounds; i++) {
@ -213,7 +213,7 @@ public class Version {
* @param v * @param v
* @return * @return
*/ */
public boolean higherOrEqual(@NotNull Version v) { public boolean higherOrEqual(@NonNull Version v) {
int rounds = Math.min(this.values.size(), v.values.size()); int rounds = Math.min(this.values.size(), v.values.size());
for(int i = 0; i < rounds; i++) { for(int i = 0; i < rounds; i++) {
@ -225,4 +225,4 @@ public class Version {
} }
} }

View File

@ -1,7 +1,7 @@
package org.mian.gitnex.helpers.ssl; package org.mian.gitnex.helpers.ssl;
/** /**
* Author Georg Lukas, modified by anonTree1417 * Author Georg Lukas, modified by opyale
*/ */
class MTMDecision { class MTMDecision {

View File

@ -7,7 +7,7 @@ import android.os.Bundle;
import org.mian.gitnex.R; import org.mian.gitnex.R;
/** /**
* Author Georg Lukas, modified by anonTree1417 * Author Georg Lukas, modified by opyale
*/ */
public class MemorizingActivity extends Activity { public class MemorizingActivity extends Activity {
@ -41,4 +41,4 @@ public class MemorizingActivity extends Activity {
} }
} }

View File

@ -39,7 +39,7 @@ import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager; import javax.net.ssl.X509TrustManager;
/** /**
* Author Georg Lukas, modified by anonTree1417 * Author Georg Lukas, modified by opyale
*/ */
public class MemorizingTrustManager implements X509TrustManager { public class MemorizingTrustManager implements X509TrustManager {
@ -605,7 +605,7 @@ public class MemorizingTrustManager implements X509TrustManager {
private boolean interactHostname(X509Certificate cert, String hostname) { private boolean interactHostname(X509Certificate cert, String hostname) {
if(interact(hostNameMessage(cert, hostname), R.string.mtm_accept_servername) == MTMDecision.DECISION_ALWAYS) { if(interact(hostNameMessage(cert, hostname), R.string.mtm_accept_server_name) == MTMDecision.DECISION_ALWAYS) {
storeCert(hostname, cert); storeCert(hostname, cert);
return true; return true;
} }

View File

@ -267,11 +267,14 @@ public interface ApiInterface {
@GET("repos/{owner}/{repo}/pulls") // get repository pull requests @GET("repos/{owner}/{repo}/pulls") // get repository pull requests
Call<List<PullRequests>> getPullRequests(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page, @Query("state") String state, @Query("limit") int limit); Call<List<PullRequests>> getPullRequests(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page, @Query("state") String state, @Query("limit") int limit);
@GET("repos/{owner}/{repo}/pulls/{index}.diff") // get pull diff file contents
Call<ResponseBody> getPullDiffContent(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Path("index") String pullIndex);
@POST("repos/{owner}/{repo}/pulls/{index}/merge") // merge a pull request @POST("repos/{owner}/{repo}/pulls/{index}/merge") // merge a pull request
Call<ResponseBody> mergePullRequest(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("index") int index, @Body MergePullRequest jsonStr); Call<ResponseBody> mergePullRequest(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("index") int index, @Body MergePullRequest jsonStr);
@GET("repos/{owner}/{repo}/commits") // get all commits @GET("repos/{owner}/{repo}/commits") // get all commits
Call<List<Commits>> getRepositoryCommits(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page, @Query("sha") String branchName); Call<List<Commits>> getRepositoryCommits(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page, @Query("sha") String branchName, @Query("limit") int limit);
@PATCH("repos/{owner}/{repo}/milestones/{index}") // close / reopen milestone @PATCH("repos/{owner}/{repo}/milestones/{index}") // close / reopen milestone
Call<JsonElement> closeReopenMilestone(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("index") int index, @Body Milestones jsonStr); Call<JsonElement> closeReopenMilestone(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("index") int index, @Body Milestones jsonStr);

View File

@ -1,39 +1,159 @@
package org.mian.gitnex.models; package org.mian.gitnex.models;
import androidx.annotation.NonNull;
import java.util.List;
/** /**
* Author M M Arif * Author M M Arif
* Author 6543
*/ */
public class FileDiffView { public class FileDiffView {
private String fileName; private String fileNewName;
private boolean fileType; private String fileOldName;
private String fileInfo; private String diffType;
private String fileContents; private String fileInfo;
private Stats stats;
private List<Content> contents;
public FileDiffView(String fileName, boolean fileType, String fileInfo, String fileContents) public class Stats {
{
this.fileName = fileName; private int lineAdded;
this.fileType = fileType; private int lineRemoved;
this.fileInfo = fileInfo;
this.fileContents = fileContents;
} public Stats(int added, int removed) {
public String getFileName() { this.lineAdded = added;
return fileName; this.lineRemoved = removed;
} }
public boolean isFileType() { public int getAdded() {
return fileType;
}
public String getFileInfo() { return lineAdded;
return fileInfo; }
}
public int getRemoved() {
return lineRemoved;
}
@NonNull
public String toString() {
return "+" + this.lineAdded + ", -" + this.lineRemoved;
}
}
public static class Content {
private int lineAdded;
private int lineRemoved;
private int oldLineStart;
private int newLineStart;
private String raw;
public Content(String content) {
this.raw = content;
}
public Content(String content, int oldStart, int newStart, int removed, int added) {
this.raw = content;
this.lineAdded = added;
this.lineRemoved = removed;
this.oldLineStart = oldStart;
this.newLineStart = newStart;
}
public String getRaw() {
return raw;
}
public int getLineAdded() {
return this.lineAdded;
}
public int getLineRemoved() {
return this.lineRemoved;
}
public int getOldLineStart() {
return this.oldLineStart;
}
public int getNewLineStart() {
return this.newLineStart;
}
}
public FileDiffView(String oldName, String newName, String diffType, String fileInfo, List<Content> fileContents) {
this.fileNewName = newName.trim();
this.fileOldName = oldName.trim();
this.diffType = diffType;
this.fileInfo = fileInfo;
this.contents = fileContents;
this.stats = new Stats(0, 0);
if(fileContents != null) {
for(Content content : this.contents) {
stats.lineAdded += content.lineAdded;
stats.lineRemoved += content.lineRemoved;
}
}
}
public String getFileName() {
if(fileOldName.length() != 0 && !fileOldName.equals(fileNewName)) {
return fileOldName + " -> " + fileNewName;
}
return fileNewName;
}
public boolean isFileBinary() {
return diffType.equals("binary");
}
public String getFileInfo() {
if(diffType.equals("binary")) {
return diffType + " " + fileInfo;
}
if(fileInfo.equals("change") && this.stats != null) {
return this.stats.toString();
}
return fileInfo;
}
@NonNull
public String toString() {
StringBuilder raw = new StringBuilder();
if(this.contents != null) {
for(Content c : this.contents) {
raw.append(c.getRaw());
}
}
return raw.toString();
}
@NonNull
public List<Content> getFileContents() {
return this.contents;
}
public String getFileContents() {
return fileContents;
}
} }

View File

@ -31,6 +31,7 @@ public class UserRepositories {
private String forks_count; private String forks_count;
private Boolean has_issues; private Boolean has_issues;
private String avatar_url; private String avatar_url;
private boolean archived;
private permissionsObject permissions; private permissionsObject permissions;
@ -167,4 +168,24 @@ public class UserRepositories {
return avatar_url; return avatar_url;
} }
public boolean isPrivateFlag() {
return privateFlag;
}
public String getOpen_pr_counter() {
return open_pr_counter;
}
public String getRelease_counter() {
return release_counter;
}
public boolean isArchived() {
return archived;
}
} }

View File

@ -9,6 +9,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.util.Base64; import android.util.Base64;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.View;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -23,271 +24,279 @@ import java.util.Locale;
public class AppUtil { public class AppUtil {
public static String strReplace(String str, String original, String replace) { public static String strReplace(String str, String original, String replace) {
return str.replace(original, replace);
}
public static boolean haveNetworkConnection(Context context) {
boolean haveConnectedWifi = false;
boolean haveConnectedMobile = false;
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
assert cm != null;
NetworkInfo[] netInfo = cm.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if (ni.getTypeName().equalsIgnoreCase("WIFI"))
if (ni.isConnected())
haveConnectedWifi = true;
if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
if (ni.isConnected())
haveConnectedMobile = true;
}
return haveConnectedWifi || haveConnectedMobile;
}
public static int getAppBuildNo(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException("Could not get package name: " + e);
}
}
public static String getAppVersion(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException("Could not get package name: " + e);
}
}
public int charactersLength(String str) {
return str.length();
}
public Boolean checkStringsWithAlphaNumeric(String str) { // [a-zA-Z0-9]
return str.matches("^[\\w]+$");
}
public Boolean checkStrings(String str) { // [a-zA-Z0-9-_. ]
return str.matches("^[\\w .-]+$");
}
public Boolean checkStringsWithAlphaNumericDashDotUnderscore(String str) { // [a-zA-Z0-9-_]
return str.matches("^[\\w.-]+$");
}
public Boolean checkStringsWithDash(String str) { // [a-zA-Z0-9-_. ]
return str.matches("^[\\w-]+$");
}
public Boolean checkIntegers(String str) {
return str.matches("\\d+");
}
public int getResponseStatusCode(String u) throws Exception {
URL url = new URL(u);
HttpURLConnection http = (HttpURLConnection) url.openConnection();
return (http.getResponseCode());
}
public static void setAppLocale(Resources resource, String locCode) {
DisplayMetrics dm = resource.getDisplayMetrics();
Configuration config = resource.getConfiguration();
config.setLocale(new Locale(locCode.toLowerCase()));
resource.updateConfiguration(config, dm);
}
public static boolean httpCheck(String url) {
String pattern = "^(http|https)://.*$";
return url.matches(pattern);
}
public static String formatFileSize(long size) {
String repoSize = null;
double m = size/1024.0;
double g = ((size/1024.0)/1024.0);
double t = (((size/1024.0)/1024.0)/1024.0);
DecimalFormat dec = new DecimalFormat("0.00");
if ( t > 1 ) {
repoSize = dec.format(t).concat(" TB");
}
else if ( g > 1 ) {
repoSize = dec.format(g).concat(" GB");
}
else if ( m > 1 ) {
repoSize = dec.format(m).concat(" MB");
}
else if ( (double) size > 1 ) {
repoSize = dec.format((double) size).concat(" KB");
}
return repoSize;
}
public static String formatFileSizeInDetail(long size) {
String fileSize = null; return str.replace(original, replace);
}
double k = size/1024.0; public static boolean hasNetworkConnection(Context context) {
double m = ((size/1024.0)/1024.0);
double g = (((size/1024.0)/1024.0)/1024.0);
double t = ((((size/1024.0)/1024.0)/1024.0)/1024.0);
DecimalFormat dec = new DecimalFormat("0.00"); boolean haveConnectedWifi = false;
boolean haveConnectedMobile = false;
if ( t > 1 ) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
fileSize = dec.format(t).concat(" TB"); assert cm != null;
} NetworkInfo[] netInfo = cm.getAllNetworkInfo();
else if ( g > 1 ) { for(NetworkInfo ni : netInfo) {
fileSize = dec.format(g).concat(" GB"); if(ni.getTypeName().equalsIgnoreCase("WIFI")) {
} if(ni.isConnected()) {
else if ( m > 1 ) { haveConnectedWifi = true;
fileSize = dec.format(m).concat(" MB"); }
} }
else if ( k > 1 ) { if(ni.getTypeName().equalsIgnoreCase("MOBILE")) {
fileSize = dec.format(k).concat(" KB"); if(ni.isConnected()) {
} haveConnectedMobile = true;
else if ( (double) size > 1 ) { }
fileSize = dec.format((double) size).concat(" B"); }
} }
return haveConnectedWifi || haveConnectedMobile;
}
return fileSize; public static int getAppBuildNo(Context context) {
} try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
}
catch(PackageManager.NameNotFoundException e) {
throw new RuntimeException("Could not get package name: " + e);
}
}
public static String customDateFormat(String customDate) { public static String getAppVersion(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionName;
}
catch(PackageManager.NameNotFoundException e) {
throw new RuntimeException("Could not get package name: " + e);
}
}
public int charactersLength(String str) {
return str.length();
}
String[] parts = customDate.split("-"); public Boolean checkStringsWithAlphaNumeric(String str) { // [a-zA-Z0-9]
final String year = parts[0]; return str.matches("^[\\w]+$");
final String month = parts[1]; }
final String day = parts[2];
String sMonth; public Boolean checkStrings(String str) { // [a-zA-Z0-9-_. ]
if (Integer.parseInt(month) < 10) { return str.matches("^[\\w .-]+$");
sMonth = "0"+ month; }
} else {
sMonth = month; public Boolean checkStringsWithAlphaNumericDashDotUnderscore(String str) { // [a-zA-Z0-9-_]
} return str.matches("^[\\w.-]+$");
}
public Boolean checkStringsWithDash(String str) { // [a-zA-Z0-9-_. ]
return str.matches("^[\\w-]+$");
}
public static Boolean checkIntegers(String str) {
return str.matches("\\d+");
}
public int getResponseStatusCode(String u) throws Exception {
URL url = new URL(u);
HttpURLConnection http = (HttpURLConnection) url.openConnection();
return (http.getResponseCode());
}
public static void setAppLocale(Resources resource, String locCode) {
DisplayMetrics dm = resource.getDisplayMetrics();
Configuration config = resource.getConfiguration();
config.setLocale(new Locale(locCode.toLowerCase()));
resource.updateConfiguration(config, dm);
}
public static String formatFileSize(long size) {
String repoSize = size + " B";
double m = size / 1024.0;
double g = ((size / 1024.0) / 1024.0);
double t = (((size / 1024.0) / 1024.0) / 1024.0);
DecimalFormat dec = new DecimalFormat("0.00");
if(t > 1) {
repoSize = dec.format(t).concat(" TB");
}
else if(g > 1) {
repoSize = dec.format(g).concat(" GB");
}
else if(m > 1) {
repoSize = dec.format(m).concat(" MB");
}
else if((double) size > 1) {
repoSize = dec.format((double) size).concat(" KB");
}
return repoSize;
}
String sDay; public static String formatFileSizeInDetail(long size) {
if (Integer.parseInt(day) < 10) {
sDay = "0"+ day;
} else {
sDay = day;
}
return year + "-" + sMonth + "-" + sDay; String fileSize = null;
} double k = size / 1024.0;
double m = ((size / 1024.0) / 1024.0);
double g = (((size / 1024.0) / 1024.0) / 1024.0);
double t = ((((size / 1024.0) / 1024.0) / 1024.0) / 1024.0);
public static String customDateCombine(String customDate) { DecimalFormat dec = new DecimalFormat("0.00");
final Calendar c = Calendar.getInstance(); if(t > 1) {
int mHour = c.get(Calendar.HOUR_OF_DAY); fileSize = dec.format(t).concat(" TB");
int mMinute = c.get(Calendar.MINUTE); }
int mSeconds = c.get(Calendar.SECOND); else if(g > 1) {
fileSize = dec.format(g).concat(" GB");
}
else if(m > 1) {
fileSize = dec.format(m).concat(" MB");
}
else if(k > 1) {
fileSize = dec.format(k).concat(" KB");
}
else if((double) size > 1) {
fileSize = dec.format((double) size).concat(" B");
}
String sMin; return fileSize;
if ((mMinute) < 10) {
sMin = "0"+ mMinute;
} else {
sMin = String.valueOf(mMinute);
}
String sSec; }
if ((mSeconds) < 10) {
sSec = "0"+ mSeconds;
} else {
sSec = String.valueOf(mSeconds);
}
return (customDate + "T" + mHour + ":" + sMin + ":" + sSec + "Z"); public static String customDateFormat(String customDate) {
} String[] parts = customDate.split("-");
final String year = parts[0];
final String month = parts[1];
final String day = parts[2];
public String encodeBase64(String str) { String sMonth;
if(Integer.parseInt(month) < 10) {
sMonth = "0" + month;
}
else {
sMonth = month;
}
String base64Str = str; String sDay;
if(!str.equals("")) { if(Integer.parseInt(day) < 10) {
byte[] data = str.getBytes(StandardCharsets.UTF_8); sDay = "0" + day;
base64Str = Base64.encodeToString(data, Base64.DEFAULT); }
} else {
sDay = day;
}
return base64Str; return year + "-" + sMonth + "-" + sDay;
} }
public String decodeBase64(String str) { public static String customDateCombine(String customDate) {
String base64Str = str; final Calendar c = Calendar.getInstance();
if(!str.equals("")) { int mHour = c.get(Calendar.HOUR_OF_DAY);
byte[] data = Base64.decode(base64Str, Base64.DEFAULT); int mMinute = c.get(Calendar.MINUTE);
base64Str = new String(data, StandardCharsets.UTF_8); int mSeconds = c.get(Calendar.SECOND);
}
return base64Str; String sMin;
if((mMinute) < 10) {
sMin = "0" + mMinute;
}
else {
sMin = String.valueOf(mMinute);
}
} String sSec;
if((mSeconds) < 10) {
sSec = "0" + mSeconds;
}
else {
sSec = String.valueOf(mSeconds);
}
public Boolean sourceCodeExtension(String ext) { return (customDate + "T" + mHour + ":" + sMin + ":" + sSec + "Z");
String[] extValues = new String[] {"md", "json", "java", "go", "php", "c", "cc", "cpp", "h", "cxx", "cyc", "m", }
"cs", "bash", "sh", "bsh", "cv", "python", "perl", "pm", "rb", "ruby", "javascript",
"coffee", "rc", "rs", "rust", "basic", "clj", "css", "dart", "lisp", "erl", "hs", "lsp", "rkt",
"ss", "llvm", "ll", "lua", "matlab", "pascal", "r", "scala", "sql", "latex", "tex", "vb", "vbs",
"vhd", "tcl", "wiki.meta", "yaml", "yml", "markdown", "xml", "proto", "regex", "py", "pl", "js",
"html", "htm", "volt", "ini", "htaccess", "conf", "gitignore", "gradle", "txt", "properties", "bat",
"twig"};
return Arrays.asList(extValues).contains(ext); public String encodeBase64(String str) {
} String base64Str = str;
if(!str.equals("")) {
byte[] data = str.getBytes(StandardCharsets.UTF_8);
base64Str = Base64.encodeToString(data, Base64.DEFAULT);
}
public Boolean pdfExtension(String ext) { return base64Str;
String[] extValues = new String[] {"pdf"}; }
return Arrays.asList(extValues).contains(ext); public String decodeBase64(String str) {
} String base64Str = str;
if(!str.equals("")) {
byte[] data = Base64.decode(base64Str, Base64.DEFAULT);
base64Str = new String(data, StandardCharsets.UTF_8);
}
public Boolean imageExtension(String ext) { return base64Str;
String[] extValues = new String[] {"jpg", "jpeg", "gif", "png", "ico"}; }
return Arrays.asList(extValues).contains(ext); public Boolean sourceCodeExtension(String ext) {
} String[] extValues = new String[]{"md", "json", "java", "go", "php", "c", "cc", "cpp", "h", "cxx", "cyc", "m", "cs", "bash", "sh", "bsh", "cv", "python", "perl", "pm", "rb", "ruby", "javascript", "coffee", "rc", "rs", "rust", "basic", "clj", "css", "dart", "lisp", "erl", "hs", "lsp", "rkt", "ss", "llvm", "ll", "lua", "matlab", "pascal", "r", "scala", "sql", "latex", "tex", "vb", "vbs", "vhd", "tcl", "wiki.meta", "yaml", "yml", "markdown", "xml", "proto", "regex", "py", "pl", "js", "html", "htm", "volt", "ini", "htaccess", "conf", "gitignore", "gradle", "txt", "properties", "bat", "twig", "cvs", "cmake", "in", "info", "spec", "m4", "am", "dist", "pam"};
public Boolean excludeFilesInFileViewerExtension(String ext) { return Arrays.asList(extValues).contains(ext);
String[] extValues = new String[] {"doc", "docx", "ppt", "pptx", "xls", "xlsx", "xlsm", "odt", }
"ott", "odf", "ods", "ots", "exe", "jar", "odg", "otg", "odp", "otp", "bin", "dmg", "psd",
"xcf"};
return Arrays.asList(extValues).contains(ext); public Boolean pdfExtension(String ext) {
} String[] extValues = new String[]{"pdf"};
public String getLastCharactersOfWord( String str, int count ) { return Arrays.asList(extValues).contains(ext);
return str.substring(str.length() - count); }
public Boolean imageExtension(String ext) {
String[] extValues = new String[]{"jpg", "jpeg", "gif", "png", "ico"};
return Arrays.asList(extValues).contains(ext);
}
public Boolean excludeFilesInFileViewerExtension(String ext) {
String[] extValues = new String[]{"doc", "docx", "ppt", "pptx", "xls", "xlsx", "xlsm", "odt", "ott", "odf", "ods", "ots", "exe", "jar", "odg", "otg", "odp", "otp", "bin", "dmg", "psd", "xcf"};
return Arrays.asList(extValues).contains(ext);
}
public String getLastCharactersOfWord(String str, int count) {
return str.substring(str.length() - count);
}
public static void setMultiVisibility(int visibility, View... views) {
for(View view : views) {
view.setVisibility(visibility);
}
}
}
} }

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topLeftRadius="12dp"
android:topRightRadius="12dp" />
<padding android:top="12dp" />
<solid android:color="?attr/primaryBackgroundColor" />
</shape>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#368F73"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M20.54,5.23l-1.39,-1.68C18.88,3.21 18.47,3 18,3H6c-0.47,0 -0.88,0.21 -1.16,0.55L3.46,5.23C3.17,5.57 3,6.02 3,6.5V19c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V6.5c0,-0.48 -0.17,-0.93 -0.46,-1.27zM12,17.5L6.5,12H10v-2h4v2h3.5L12,17.5zM5.12,5l0.81,-1h12l0.94,1H5.12z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#368F73"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M8.59,16.34l4.58,-4.59 -4.58,-4.59L10,5.75l6,6 -6,6z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#368F73"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M9.4,16.6L4.8,12l4.6,-4.6L8,6l-6,6 6,6 1.4,-1.4zM14.6,16.6l4.6,-4.6 -4.6,-4.6L16,6l6,6 -6,6 -1.4,-1.4z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#368F73"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
</vector>

View File

@ -9,8 +9,8 @@
android:right="1dp" android:right="1dp"
android:left="1dp"> android:left="1dp">
<shape> <shape>
<corners android:radius="15dp"/> <corners android:radius="10dp"/>
<solid android:color="@color/divider"/> <solid android:color="?attr/inputBackgroundColor"/>
</shape> </shape>
</item> </item>
@ -23,9 +23,9 @@
<scale android:scaleWidth="100%"> <scale android:scaleWidth="100%">
<shape> <shape>
<corners android:radius="15dp" /> <corners android:radius="10dp" />
</shape> </shape>
</scale> </scale>
</item> </item>
</layer-list> </layer-list>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="3dp"/>
<solid android:color="@color/releasePre" />
</shape>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="@color/releasePre">
</solid>
<corners
android:radius="3dp">
</corners>
</shape>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="@color/releaseStable">
</solid>
<corners
android:radius="3dp">
</corners>
</shape>

View File

@ -54,7 +54,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor" android:background="?attr/primaryBackgroundColor"
android:padding="4dp"
android:scrollbars="vertical" /> android:scrollbars="vertical" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
@ -70,4 +69,4 @@
android:textSize="20sp" android:textSize="20sp"
android:visibility="visible" /> android:visibility="visible" />
</LinearLayout> </LinearLayout>

View File

@ -58,7 +58,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor" android:background="?attr/primaryBackgroundColor"
android:padding="4dp"
android:scrollbars="vertical" /> android:scrollbars="vertical" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
@ -83,4 +82,4 @@
android:indeterminate="true" android:indeterminate="true"
android:visibility="visible" /> android:visibility="visible" />
</RelativeLayout> </RelativeLayout>

View File

@ -160,7 +160,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/releaseTypeText" android:text="@string/releaseTypeText"
android:checked="true" android:checked="false"
android:textSize="16sp" android:textSize="16sp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:textColor="?attr/primaryTextColor"/> android:textColor="?attr/primaryTextColor"/>
@ -170,7 +170,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/releaseDraftText" android:text="@string/releaseDraftText"
android:checked="true" android:checked="false"
android:textSize="16sp" android:textSize="16sp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:textColor="?attr/primaryTextColor"/> android:textColor="?attr/primaryTextColor"/>
@ -194,4 +194,4 @@
</ScrollView> </ScrollView>
</LinearLayout> </LinearLayout>

View File

@ -74,7 +74,7 @@
android:background="@drawable/shape_inputs" android:background="@drawable/shape_inputs"
android:textColor="?attr/inputTextColor" android:textColor="?attr/inputTextColor"
android:textColorHint="?attr/hintColor" android:textColorHint="?attr/hintColor"
android:textColorHighlight="?attr/primaryTextColor"/> android:textColorHighlight="?attr/primaryTextColor" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -97,7 +97,7 @@
android:background="@drawable/shape_inputs" android:background="@drawable/shape_inputs"
android:textColor="?attr/inputTextColor" android:textColor="?attr/inputTextColor"
android:textColorHint="?attr/hintColor" android:textColorHint="?attr/hintColor"
android:textColorHighlight="?attr/primaryTextColor"/> android:textColorHighlight="?attr/primaryTextColor" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -105,7 +105,7 @@
android:text="@string/newTeamPermission" android:text="@string/newTeamPermission"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="16sp" android:textSize="16sp"
android:layout_marginTop="10dp"/> android:layout_marginTop="10dp" />
<TextView <TextView
android:id="@+id/teamPermission" android:id="@+id/teamPermission"
@ -116,10 +116,10 @@
android:textSize="14sp" android:textSize="14sp"
tools:ignore="Autofill" tools:ignore="Autofill"
android:background="@drawable/shape_inputs" android:background="@drawable/shape_inputs"
android:textColor="@color/white" android:textColor="?attr/inputTextColor"
android:textColorHint="@color/white" android:textColorHint="?attr/hintColor"
android:inputType="none" android:textColorHighlight="?attr/primaryTextColor"
android:textColorHighlight="@color/white"/> android:inputType="none" />
<TextView <TextView
android:id="@+id/teamPermissionDetail" android:id="@+id/teamPermissionDetail"
@ -128,7 +128,7 @@
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="12sp" android:textSize="12sp"
android:gravity="start" android:gravity="start"
android:visibility="gone"/> android:visibility="gone" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -136,7 +136,7 @@
android:text="@string/newTeamAccessControls" android:text="@string/newTeamAccessControls"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="16sp" android:textSize="16sp"
android:layout_marginTop="10dp"/> android:layout_marginTop="10dp" />
<TextView <TextView
android:id="@+id/teamAccessControls" android:id="@+id/teamAccessControls"
@ -147,16 +147,16 @@
android:textSize="14sp" android:textSize="14sp"
tools:ignore="Autofill" tools:ignore="Autofill"
android:background="@drawable/shape_inputs" android:background="@drawable/shape_inputs"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/inputTextColor"
android:textColorHint="?attr/primaryTextColor" android:textColorHint="?attr/hintColor"
android:inputType="none" android:textColorHighlight="?attr/primaryTextColor"
android:textColorHighlight="?attr/primaryTextColor"/> android:inputType="none" />
<TextView <TextView
android:id="@+id/teamAccessControlsArray" android:id="@+id/teamAccessControlsArray"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone"/> android:visibility="gone" />
<Button <Button
android:id="@+id/createTeamButton" android:id="@+id/createTeamButton"
@ -171,10 +171,10 @@
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="35dp"/> android:layout_height="35dp" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</LinearLayout> </LinearLayout>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:background="?attr/primaryBackgroundColor" android:background="?attr/primaryBackgroundColor"
android:orientation="vertical" android:orientation="vertical"
android:gravity="center" android:gravity="center"
@ -239,4 +239,4 @@
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@ -4,9 +4,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="8dp" android:paddingTop="6dp"
android:background="?attr/primaryBackgroundColor" android:paddingBottom="12dp"
android:paddingTop="8dp"> android:background="?attr/primaryBackgroundColor">
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -27,10 +27,10 @@
android:drawablePadding="24dp" android:drawablePadding="24dp"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="16sp" android:textSize="16sp"
android:padding="16dp" /> android:padding="12dp" />
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</LinearLayout> </LinearLayout>

View File

@ -4,9 +4,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="8dp" android:paddingTop="6dp"
android:background="?attr/primaryBackgroundColor" android:paddingBottom="12dp"
android:paddingTop="8dp"> android:background="?attr/primaryBackgroundColor">
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -27,10 +27,10 @@
android:drawablePadding="24dp" android:drawablePadding="24dp"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="16sp" android:textSize="16sp"
android:padding="16dp" /> android:padding="12dp" />
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</LinearLayout> </LinearLayout>

View File

@ -4,9 +4,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="8dp" android:paddingTop="6dp"
android:background="?attr/primaryBackgroundColor" android:paddingBottom="12dp"
android:paddingTop="8dp"> android:background="?attr/primaryBackgroundColor">
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -27,7 +27,7 @@
android:drawablePadding="24dp" android:drawablePadding="24dp"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="16sp" android:textSize="16sp"
android:padding="16dp" /> android:padding="12dp" />
<TextView <TextView
android:id="@+id/commentMenuDelete" android:id="@+id/commentMenuDelete"
@ -39,7 +39,31 @@
android:drawablePadding="24dp" android:drawablePadding="24dp"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="16sp" android:textSize="16sp"
android:padding="16dp" /> android:padding="12dp" />
<TextView
android:id="@+id/commentMenuQuote"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/menuQuoteText"
android:drawableStart="@drawable/ic_comment"
android:drawablePadding="24dp"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:padding="12dp" />
<TextView
android:id="@+id/commentMenuCopy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/menuCopyText"
android:drawableStart="@drawable/ic_content_copy"
android:drawablePadding="24dp"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:padding="12dp" />
<TextView <TextView
android:id="@+id/issueCommentShare" android:id="@+id/issueCommentShare"
@ -51,10 +75,10 @@
android:drawablePadding="24dp" android:drawablePadding="24dp"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="16sp" android:textSize="16sp"
android:padding="16dp" /> android:padding="12dp" />
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</LinearLayout> </LinearLayout>

View File

@ -4,9 +4,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="8dp" android:paddingTop="6dp"
android:background="?attr/primaryBackgroundColor" android:paddingBottom="12dp"
android:paddingTop="8dp"> android:background="?attr/primaryBackgroundColor">
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -27,7 +27,7 @@
android:drawablePadding="24dp" android:drawablePadding="24dp"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="16sp" android:textSize="16sp"
android:padding="16dp" /> android:padding="12dp" />
<TextView <TextView
android:id="@+id/closedIssues" android:id="@+id/closedIssues"
@ -39,10 +39,10 @@
android:drawablePadding="24dp" android:drawablePadding="24dp"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="16sp" android:textSize="16sp"
android:padding="16dp" /> android:padding="12dp" />
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</LinearLayout> </LinearLayout>

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