Compare commits

..

16 Commits

604 changed files with 15919 additions and 36244 deletions

View File

@ -1,65 +1,21 @@
--- ---
kind: pipeline kind: pipeline
type: docker name: gitnex-ci-test
name: tests
steps: steps:
- name: unit-tests - name: test
image: nextcloudci/android:android-49 image: nextcloudci/android:android-49
depends_on: [ clone ]
commands: commands:
- ./gradlew test - ./gradlew test
- name: check-formatting
image: zosiab/eclint:latest
depends_on: [ clone ]
commands:
- git pull origin master
- eclint check $(git diff --name-only origin/master)
# This may be used in the future, because it makes of intellij's native code inspection/formatting capabilities.
# Additional information: https://www.jetbrains.com/help/idea/command-line-formatter.html
#
# - name: do-or-check-formatting
# image: dlsniper/docker-intellij
# depends_on: [ clone ]
# commands:
# - /opt/intellij/bin/idea.sh inspect/format ...
#
# - name: do-or-check-formatting
# image: dlsniper/docker-intellij
# depends_on: [ clone ]
# commands:
# - /opt/intellij/bin/idea.sh format -s .idea/codeStyles/Project.xml -m *.java app/src/main/java
trigger: trigger:
event: event:
- pull_request - pull_request
--- ---
kind: pipeline kind: pipeline
type: docker name: gitnex-ci-build
name: code-analysis
steps:
- name: check-global-formatting
image: zosiab/eclint:latest
depends_on: [ clone ]
commands:
- eclint check $(git ls-files)
trigger:
event:
- push
branch:
- master
---
kind: pipeline
type: docker
name: build
steps: steps:
@ -68,35 +24,6 @@ steps:
commands: commands:
- ./gradlew build - ./gradlew build
- name: sign
image: nextcloudci/android:android-49
environment:
BOT_TOKEN:
from_secret: BOT_TOKEN
KS_PASS:
from_secret: KS_PASS
KEY_PASS:
from_secret: KEY_PASS
OUTPUT: signed.apk
GITEA: https://gitea.com
KS_FILE: ci_keystore.jks
KS_REPO:
from_secret: KS_REPO
commands:
- ./scripts/sign-build.sh
- name: publish
image: vividboarder/drone-webdav
environment:
WEBDAV_USERNAME: GitNexBot
WEBDAV_PASSWORD:
from_secret: NC_TOKEN
PLUGIN_FILE: 'signed.apk'
PLUGIN_TIMEOUT: 180
PLUGIN_ATTEMPTS: 5
PLUGIN_DESTINATION: 'https://cloud.swatian.com/remote.php/dav/files/GitNexBot/gitnex/builds/latest.apk'
PLUGIN_CUSTOM_ARGUMENTS: '--progress-bar'
trigger: trigger:
event: event:
- push - push

View File

@ -1,25 +0,0 @@
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 150
[*.java]
indent_style = tab
line_comment = //
block_comment_start = /*
block_comment = *
block_comment_end = */
[*.json]
indent_size = 2
[{*.yml,*.yaml}]
indent_size = 2
[*.md]
trim_trailing_whitespace = false
insert_final_newline = false

1
.gitattributes vendored
View File

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

View File

@ -1,32 +0,0 @@
## # What do you want to address?
(This step is required; examples are shown below)
- [ ] Bug
- [ ] Feature
- [ ] Suggestion
## # Describe your matter briefly
(This step is required)
##### What did you expect? (Useful when addressing bugs)
---
_(This step is optional)_
##### Some additional details (Useful, when we are trying to reproduce a bug)
---
_(This step is optional; an example is shown below)_
* The version of **Gitea** you are using:
* The version of **GitNex** you are using:
* Phone **OS** version and model:
* The type of certificate you are using (self-signed, signed):
* How you used to log in (via password or token):
##### We would appreciate some screenshots or stacktrace's, but this is also not required.
---
_(Screenshots and stacktrace's can go here)_
#### Thank you for your time.

View File

@ -1,8 +0,0 @@
Please check the following:
1. Make sure you are targeting the `master` branch, pull requests on release branches are only allowed for bug fixes.
2. Read contributing guidelines: [CONTRIBUTING.md](https://gitea.com/GitNex/GitNex/src/branch/master/CONTRIBUTING.md)
3. Please follow the [Code-Standards](https://gitea.com/gitnex/GitNex/wiki/Code-Standards)
4. Describe what your pull request does and which issue youre targeting (create one if does not exist)
**You MUST delete the content above including this line before posting, otherwise your pull request will be invalid.**

4
.gitignore vendored
View File

@ -8,9 +8,6 @@
*.ap_ *.ap_
*.aab *.aab
# Release dir
app/release/*
# Files for the ART/Dalvik VM # Files for the ART/Dalvik VM
*.dex *.dex
@ -51,7 +48,6 @@ captures/
.idea/dictionaries .idea/dictionaries
.idea/libraries .idea/libraries
.idea/caches .idea/caches
!.idea/codeStyles
# Keystore files # Keystore files
# Uncomment the following lines if you do not want to check your keystore files in. # Uncomment the following lines if you do not want to check your keystore files in.

View File

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

View File

@ -1,165 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JavaCodeStyleSettings>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="android" withSubpackages="true" static="false" />
<package name="androidx" withSubpackages="true" static="false" />
<package name="com" withSubpackages="true" static="false" />
<package name="junit" withSubpackages="true" static="false" />
<package name="net" withSubpackages="true" static="false" />
<package name="org" withSubpackages="true" static="false" />
<package name="java" withSubpackages="true" static="false" />
<package name="javax" withSubpackages="true" static="false" />
<package name="" withSubpackages="true" static="false" />
<package name="" withSubpackages="true" static="true" />
</value>
</option>
</JavaCodeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="RIGHT_MARGIN" value="220" />
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
<option name="BLANK_LINES_BEFORE_METHOD_BODY" value="1" />
<option name="BLANK_LINES_AROUND_FIELD_IN_INTERFACE" value="1" />
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
<option name="BLANK_LINES_AFTER_ANONYMOUS_CLASS_HEADER" value="1" />
<option name="BLANK_LINES_BEFORE_CLASS_END" value="1" />
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="FINALLY_ON_NEW_LINE" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_TRY_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_SYNCHRONIZED_PARENTHESES" value="false" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="TERNARY_OPERATION_WRAP" value="1" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="3" />
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
<option name="SMART_TABS" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View File

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

View File

@ -7,11 +7,6 @@ Patches, enhancements, features are always welcome. The PR should focus on the s
Please ask if you are not sure about the scope of work to be submitted to avoid waste of time spent on the work. Please ask if you are not sure about the scope of work to be submitted to avoid waste of time spent on the work.
**Code Standards**
Please follow the code standards, this will help other developers to understand your code too.
It also helps maintaining the code afterwards.
It is documented in the Wiki: [Code-Standards](https://codeberg.org/gitnex/GitNex/wiki/Code-Standards)
**How to submit a PR** **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,7 +3,6 @@ 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
@ -19,7 +18,6 @@ This part lists all PUBLIC individuals having contributed content to the transla
* erardiflorian * erardiflorian
* IndeedNotJames * IndeedNotJames
* jaqra * jaqra
* Lafriks
* ljoonal * ljoonal
* Lunny Xiao (xiaolunwen) * Lunny Xiao (xiaolunwen)
* lxs * lxs

63
LICENSE
View File

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

View File

@ -1,22 +1,27 @@
[![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) [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Release](https://img.shields.io/badge/dynamic/json.svg?label=release&url=https://gitea.com/api/v1/repos/gitnex/GitNex/releases&query=$[0].tag_name)](https://gitea.com/gitnex/GitNex/releases)
[![Build Status](https://drone.gitea.com/api/badges/gitnex/GitNex/status.svg)](https://drone.gitea.com/gitnex/GitNex)
[![Crowdin](https://badges.crowdin.net/gitnex/localized.svg)](https://crowdin.com/project/gitnex)
[<img alt="Become a Patroen" src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" height="40"/>](https://www.patreon.com/mmarif) [<img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg" 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)
# GitNex - Android client for Gitea # GitNex - Android client for Gitea
GitNex is a free, open-source Android client for Git repository management tool Gitea. Gitea is a community managed fork of Gogs, lightweight code hosting solution written in Go. GitNex is a free, open-source Android client for Git repository management tool Gitea. Gitea is a community managed fork of Gogs, lightweight code hosting solution written in Go.
GitNex is licensed under GPLv3 License. See the LICENSE file for the full license text. No trackers are used and source code is available here for anyone to audit. GitNex is licensed under GPLv3 License. See the LICENSE file for the full license text.
No trackers are used and source code is available here for anyone to audit.
## Downloads ## Downloads
[<img alt='Get it on F-droid' src='https://gitlab.com/fdroid/artwork/raw/master/badge/get-it-on.png' height="80"/>](https://f-droid.org/en/packages/org.mian.gitnex/) [<img alt='Get it on F-droid' src='https://gitlab.com/fdroid/artwork/raw/master/badge/get-it-on.png' height="80"/>](https://f-droid.org/en/packages/org.mian.gitnex/)
[<img alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png' height="80"/>](https://play.google.com/store/apps/details?id=org.mian.gitnex) [<img alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png' height="80"/>](https://play.google.com/store/apps/details?id=org.mian.gitnex)
[<img alt='Download builds and releases' src='assets/apk-badge.png' height="82"/>](https://cloud.swatian.com/s/DN7E5xxtaw4fRbE) [<img alt='Download APK' src='https://gitnex.com/img/download-apk.png' height="80"/>](https://gitea.com/gitnex/GitNex/releases)
## 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 Gitea **1.10.x** stable release or later. Below this may not work as one would expect because of the newly added objects to the API at later versions. Please consider updating your Gitea server.
Check the versions [compatibility page](https://codeberg.org/gitnex/GitNex/wiki/Compatibility) which lists all the supported versions with compatibility ratio. Check the versions [compatibility page](https://gitea.com/gitnex/GitNex/wiki/Compatibility) which lists all the supported versions with compatibility ratio.
## Build from source ## 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.
@ -24,51 +29,48 @@ Option 1 - Download the source code, open it in Android Studio and build it ther
Option 2 - Open terminal(Linux) and cd to the project dir. Run `./gradlew build`. Option 2 - Open terminal(Linux) and cd to the project dir. Run `./gradlew build`.
## Features ## Features
- Multiple accounts support
- Repositories / issues/ org list
- File and directory browser - File and directory browser
- File viewer
- Create files - Create files
- Explore repositories - Explore repositories
- Issues list
- Pull requests - Pull requests
- Files diff for PRs - Merge pull request
- Notifications - [MANY MORE](https://gitea.com/gitnex/GitNex/wiki/Features)
- Drafts
- [MANY MORE](https://codeberg.org/gitnex/GitNex/wiki/Features)
## Contributing ## Contributing
[CONTRIBUTING](https://codeberg.org/gitnex/GitNex/src/branch/master/CONTRIBUTING.md) [CONTRIBUTING](https://gitea.com/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://codeberg.org/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://gitea.com/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://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/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/005.png" alt="005.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/006.png" alt="006.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/007.png" alt="007.png" width="200"/> | <img src="https://codeberg.org/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/008.png" alt="008.png" width="200"/> <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/005.png" alt="005.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/006.png" alt="006.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/007.png" alt="007.png" width="200"/> | <img src="https://gitea.com/gitnex/GitNex/raw/branch/master/fastlane/metadata/android/en-US/images/phoneScreenshots/008.png" alt="008.png" width="200"/>
## FAQ ## FAQ
[Faq](https://codeberg.org/gitnex/GitNex/wiki/FAQ) [Faq](https://gitea.com/gitnex/GitNex/wiki/FAQ)
## Links ## Links
[Website](https://gitnex.com) [Website](https://gitnex.com)
[Wiki](https://codeberg.org/gitnex/GitNex/wiki/Home) [Wiki](https://gitea.com/gitnex/GitNex/wiki/Home)
[Website Repository](https://gitlab.com/mmarif4u/gitnex-website) [Website Repository](https://gitlab.com/mmarif4u/gitnex-website)
[Troubleshoot Guide](https://codeberg.org/gitnex/GitNex/wiki/Troubleshoot-Guide) [Troubleshoot Guide](https://gitea.com/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,9 +89,5 @@ Thanks to all the open source libraries, contributors and donators.
- Apache/commons-io - Apache/commons-io
- Caverock/androidsvg - Caverock/androidsvg
- Droidsonroids.gif/android-gif-drawable - Droidsonroids.gif/android-gif-drawable
- Barteksc/androidPdfViewer
- 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,17 +6,13 @@ android {
applicationId "org.mian.gitnex" applicationId "org.mian.gitnex"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
versionCode 310 versionCode 82
versionName "3.1.0" versionName "2.3.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
buildFeatures {
viewBinding = true
}
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
@ -24,46 +20,31 @@ android {
//checkReleaseBuilds false //checkReleaseBuilds false
abortOnError false abortOnError false
} }
compileOptions {
targetCompatibility = "8"
sourceCompatibility = "8"
}
defaultConfig{
vectorDrawables.useSupportLibrary = true
}
}
configurations {
cleanedAnnotations
compile.exclude group: 'org.jetbrains', module: 'annotations'
} }
dependencies { dependencies {
def lifecycle_version = "2.3.0-alpha06" def lifecycle_version = "2.2.0-rc02"
def markwon_version = "4.4.0" final def markwon_version = "4.1.1"
def work_version = "2.4.0"
def acra = "5.5.0"
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "androidx.appcompat:appcompat:1.3.0-alpha01" implementation "androidx.appcompat:appcompat:1.1.0"
implementation "com.google.android.material:material:1.3.0-alpha02" implementation "com.google.android.material:material:1.2.0-alpha02"
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.12"
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.8.0' implementation "com.squareup.okhttp3:okhttp:3.12.1"
implementation "com.google.code.gson:gson:2.8.6" implementation "com.google.code.gson:gson:2.8.5"
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.9.0' implementation "com.squareup.retrofit2:retrofit:2.5.0"
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation "com.squareup.retrofit2:converter-gson:2.5.0"
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' implementation "com.squareup.retrofit2:converter-scalars:2.5.0"
implementation 'com.squareup.okhttp3:logging-interceptor:4.8.0' implementation "com.squareup.okhttp3:logging-interceptor:3.12.1"
implementation 'org.ocpsoft.prettytime:prettytime:4.0.5.Final' implementation "org.ocpsoft.prettytime:prettytime:4.0.1.Final"
implementation "com.vdurmont:emoji-java:5.1.1" implementation "com.vdurmont:emoji-java:4.0.0"
implementation "com.pes.materialcolorpicker:library:1.2.5" implementation "com.pes.materialcolorpicker:library:1.2.5"
implementation "io.noties.markwon:core:$markwon_version" implementation "io.noties.markwon:core:$markwon_version"
implementation "io.noties.markwon:ext-latex:$markwon_version" implementation "io.noties.markwon:ext-latex:$markwon_version"
@ -82,18 +63,10 @@ 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:2.6"
implementation 'org.apache.commons:commons-lang3:3.11'
implementation "com.github.chrisbanes:PhotoView:2.3.0" implementation "com.github.chrisbanes:PhotoView:2.3.0"
implementation "com.github.barteksc:android-pdf-viewer:3.2.0-beta.1" implementation "com.pddstudio:highlightjs-android:1.5.0"
implementation "ch.acra:acra-mail:$acra"
implementation "ch.acra:acra-limiter:$acra"
implementation "ch.acra:acra-notification:$acra"
implementation "androidx.room:room-runtime:2.2.5"
annotationProcessor "androidx.room:room-compiler:2.2.5"
implementation "androidx.work:work-runtime:$work_version"
implementation "com.eightbitlab:blurview:1.6.3"
implementation "io.mikael:urlbuilder:2.0.9"
} }

View File

@ -1,10 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.mian.gitnex"> package="org.mian.gitnex">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application <application
@ -12,17 +10,15 @@
android:icon="@mipmap/app_logo" android:icon="@mipmap/app_logo"
android:label="@string/app_name" android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
android:resizeableActivity="true"
android:roundIcon="@mipmap/app_logo_round" android:roundIcon="@mipmap/app_logo_round"
android:supportsRtl="true" android:supportsRtl="true"
tools:targetApi="n"> android:theme="@style/AppTheme">
<activity android:name=".activities.MergePullRequestActivity"></activity>
<activity android:name=".activities.MergePullRequestActivity" />
<activity <activity
android:name=".activities.FileViewActivity" android:name=".activities.FileViewActivity"
android:theme="@style/AppTheme.NoActionBar" /> android:theme="@style/AppTheme.NoActionBar" />
<activity <activity
android:name=".activities.CreateFileActivity" android:name=".activities.NewFileActivity"
android:theme="@style/AppTheme.NoActionBar" /> android:theme="@style/AppTheme.NoActionBar" />
<activity <activity
android:name=".activities.RepoWatchersActivity" android:name=".activities.RepoWatchersActivity"
@ -43,14 +39,16 @@
<activity android:name=".activities.ProfileEmailActivity" /> <activity android:name=".activities.ProfileEmailActivity" />
<activity android:name=".activities.AddCollaboratorToRepositoryActivity" /> <activity android:name=".activities.AddCollaboratorToRepositoryActivity" />
<activity android:name=".activities.CreateTeamByOrgActivity" /> <activity android:name=".activities.CreateTeamByOrgActivity" />
<activity android:name=".activities.OrganizationTeamMembersActivity" /> <activity android:name=".activities.OrgTeamMembersActivity" />
<activity <activity
android:name=".activities.OrganizationDetailActivity" android:name=".activities.OrgDetailActivity"
android:label="@string/title_activity_org_detail" android:label="@string/title_activity_org_detail"
android:theme="@style/AppTheme.NoActionBar" /> android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".activities.SponsorsActivity" />
<activity android:name=".activities.CreditsActivity" />
<activity android:name=".activities.CreateLabelActivity" /> <activity android:name=".activities.CreateLabelActivity" />
<activity android:name=".activities.CreateIssueActivity" /> <activity android:name=".activities.CreateIssueActivity" />
<activity android:name=".activities.CreateMilestoneActivity" /> <activity android:name=".activities.NewMilestoneActivity" />
<activity android:name=".activities.ReplyToIssueActivity" /> <activity android:name=".activities.ReplyToIssueActivity" />
<activity <activity
android:name=".activities.IssueDetailActivity" android:name=".activities.IssueDetailActivity"
@ -59,7 +57,7 @@
android:name=".activities.RepoDetailActivity" android:name=".activities.RepoDetailActivity"
android:label="@string/title_activity_repo_detail" android:label="@string/title_activity_repo_detail"
android:theme="@style/AppTheme.NoActionBar" /> android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".activities.MainActivity" android:theme="@android:style/Theme.NoTitleBar" android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"> <activity android:name=".activities.MainActivity">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -68,28 +66,11 @@
</activity> </activity>
<activity <activity
android:name=".activities.LoginActivity" android:name=".activities.LoginActivity"
android:launchMode="singleTask" android:theme="@android:style/Theme.NoTitleBar"/> android:launchMode="singleTask" />
<activity android:name=".activities.CreateRepoActivity" /> <activity android:name=".activities.NewRepoActivity" />
<activity android:name=".activities.CreateOrganizationActivity" /> <activity android:name=".activities.NewOrganizationActivity" />
<activity android:name=".activities.OpenRepoInBrowserActivity" /> <activity android:name=".activities.OpenRepoInBrowserActivity" />
<activity android:name=".activities.FileDiffActivity" /> <activity android:name=".activities.FileDiffActivity" />
<activity android:name=".activities.CommitsActivity" />
<activity android:name=".helpers.ssl.MemorizingActivity" android:theme="@android:style/Theme.Material.Dialog" />
<activity android:name=".activities.SettingsAppearanceActivity" />
<activity android:name=".activities.SettingsFileViewerActivity" />
<activity android:name=".activities.SettingsSecurityActivity" />
<activity android:name=".activities.SettingsTranslationActivity" />
<activity android:name=".activities.SettingsReportsActivity" />
<activity android:name=".activities.AddNewTeamMemberActivity" />
<activity android:name=".activities.SettingsDraftsActivity" />
<activity android:name=".activities.RepoForksActivity" />
<activity android:name=".activities.AddNewAccountActivity" />
<!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>
<!-- Version >= 3.0. DeX Dual Mode support -->
<meta-data android:name="com.samsung.android.multidisplay.keep_process_alive" android:value="true"/>
</application> </application>
</manifest> </manifest>

File diff suppressed because one or more lines are too long

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,16 +2,16 @@ package org.mian.gitnex.actions;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.AddCollaboratorToRepositoryActivity; import org.mian.gitnex.activities.AddCollaboratorToRepositoryActivity;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators; import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Permission; import org.mian.gitnex.models.Permission;
import org.mian.gitnex.util.TinyDB;
import androidx.annotation.NonNull;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -47,7 +47,7 @@ public class CollaboratorActions {
if(response.isSuccessful()) { if(response.isSuccessful()) {
if(response.code() == 204) { if(response.code() == 204) {
Toasty.success(context, context.getString(R.string.removeCollaboratorToastText)); Toasty.info(context, context.getString(R.string.removeCollaboratorToastText));
((AddCollaboratorToRepositoryActivity)context).finish(); ((AddCollaboratorToRepositoryActivity)context).finish();
//Log.i("addCollaboratorSearch", addCollaboratorSearch.getText().toString()); //Log.i("addCollaboratorSearch", addCollaboratorSearch.getText().toString());
//tinyDb.putBoolean("updateDataSet", true); //tinyDb.putBoolean("updateDataSet", true);
@ -66,17 +66,17 @@ public class CollaboratorActions {
} }
else if(response.code() == 403) { else if(response.code() == 403) {
Toasty.error(context, context.getString(R.string.authorizeError)); Toasty.info(context, context.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
Toasty.warning(context, context.getString(R.string.apiNotFound)); Toasty.info(context, context.getString(R.string.apiNotFound));
} }
else { else {
Toasty.error(context, context.getString(R.string.genericError)); Toasty.info(context, context.getString(R.string.genericError));
} }
@ -117,7 +117,7 @@ public class CollaboratorActions {
if(response.isSuccessful()) { if(response.isSuccessful()) {
if(response.code() == 204) { if(response.code() == 204) {
Toasty.success(context, context.getString(R.string.addCollaboratorToastText)); Toasty.info(context, context.getString(R.string.addCollaboratorToastText));
((AddCollaboratorToRepositoryActivity)context).finish(); ((AddCollaboratorToRepositoryActivity)context).finish();
//AddCollaboratorToRepositoryActivity usersSearchData = new AddCollaboratorToRepositoryActivity(); //AddCollaboratorToRepositoryActivity usersSearchData = new AddCollaboratorToRepositoryActivity();
//usersSearchData.loadUserSearchList(instanceUrl, instanceToken, searchKeyword, context); //usersSearchData.loadUserSearchList(instanceUrl, instanceToken, searchKeyword, context);
@ -134,17 +134,17 @@ public class CollaboratorActions {
} }
else if(response.code() == 403) { else if(response.code() == 403) {
Toasty.error(context, context.getString(R.string.authorizeError)); Toasty.info(context, context.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
Toasty.warning(context, context.getString(R.string.apiNotFound)); Toasty.info(context, context.getString(R.string.apiNotFound));
} }
else { else {
Toasty.error(context, context.getString(R.string.genericError)); Toasty.info(context, context.getString(R.string.genericError));
} }

View File

@ -2,18 +2,17 @@ package org.mian.gitnex.actions;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity; import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.IssueComments;
import org.mian.gitnex.models.UpdateIssueState; import org.mian.gitnex.models.UpdateIssueState;
import org.mian.gitnex.models.IssueComments;
import org.mian.gitnex.util.TinyDB;
import androidx.annotation.NonNull;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -23,263 +22,143 @@ import retrofit2.Callback;
public class IssueActions { public class IssueActions {
public static void editIssueComment(final Context ctx, final int commentId, final String commentBody, long draftIdOnCreate) { public static void editIssueComment(final Context context, final int commentId, final String commentBody) {
final TinyDB tinyDb = new TinyDB(ctx); final TinyDB tinyDb = new TinyDB(context);
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");
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 repoName = parts[1];
IssueComments commentBodyJson = new IssueComments(commentBody); IssueComments commentBodyJson = new IssueComments(commentBody);
Call<IssueComments> call; Call<IssueComments> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().patchIssueComment(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, commentId, commentBodyJson); call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.patchIssueComment(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, commentId, commentBodyJson);
call.enqueue(new Callback<IssueComments>() { call.enqueue(new Callback<IssueComments>() {
@Override @Override
public void onResponse(@NonNull Call<IssueComments> call, @NonNull retrofit2.Response<IssueComments> response) { public void onResponse(@NonNull Call<IssueComments> call, @NonNull retrofit2.Response<IssueComments> response) {
if(response.isSuccessful()) { if(response.isSuccessful()) {
if(response.code() == 200) { if(response.code() == 200) {
tinyDb.putBoolean("commentEdited", true); tinyDb.putBoolean("commentEdited", true);
Toasty.info(ctx, ctx.getString(R.string.editCommentUpdatedText)); Toasty.info(context, context.getString(R.string.editCommentUpdatedText));
((ReplyToIssueActivity)context).finish();
DraftsApi draftsApi = new DraftsApi(ctx); }
draftsApi.deleteSingleDraft((int) draftIdOnCreate); }
else if(response.code() == 401) {
((ReplyToIssueActivity) ctx).finish(); AlertDialogs.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle),
context.getResources().getString(R.string.alertDialogTokenRevokedMessage),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
} }
} else if(response.code() == 403) {
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle), ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); Toasty.info(context, context.getString(R.string.authorizeError));
} }
else if(response.code() == 403) { else if(response.code() == 404) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); Toasty.info(context, context.getString(R.string.apiNotFound));
} }
else if(response.code() == 404) { else {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)); Toasty.info(context, context.getString(R.string.genericError));
} }
else {
Toasty.error(ctx, ctx.getString(R.string.genericError)); }
} @Override
public void onFailure(@NonNull Call<IssueComments> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
} }
@Override public static void closeReopenIssue(final Context context, final int issueIndex, final String issueState) {
public void onFailure(@NonNull Call<IssueComments> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString()); final TinyDB tinyDb = new TinyDB(context);
} final String instanceUrl = tinyDb.getString("instanceUrl");
}); final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
} UpdateIssueState issueStatJson = new UpdateIssueState(issueState);
Call<JsonElement> call;
public static void closeReopenIssue(final Context ctx, final int issueIndex, final String issueState) { call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.closeReopenIssue(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueStatJson);
final TinyDB tinyDb = new TinyDB(ctx); call.enqueue(new Callback<JsonElement>() {
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
UpdateIssueState issueStatJson = new UpdateIssueState(issueState); @Override
Call<JsonElement> call; public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().closeReopenIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueStatJson); if(response.isSuccessful()) {
if(response.code() == 201) {
call.enqueue(new Callback<JsonElement>() { tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("resumeClosedIssues", true);
if(issueState.equals("closed")) {
Toasty.info(context, context.getString(R.string.issueStateClosed));
}
else if(issueState.equals("open")) {
Toasty.info(context, context.getString(R.string.issueStateReopened));
}
@Override }
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) { }
else if(response.code() == 401) {
if(response.isSuccessful()) { AlertDialogs.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle),
if(response.code() == 201) { context.getResources().getString(R.string.alertDialogTokenRevokedMessage),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
tinyDb.putBoolean("resumeIssues", true); }
tinyDb.putBoolean("resumeClosedIssues", true); else if(response.code() == 403) {
if(issueState.equals("closed")) { Toasty.info(context, context.getString(R.string.authorizeError));
Toasty.success(ctx, ctx.getString(R.string.issueStateClosed)); }
tinyDb.putString("issueState", "closed"); else if(response.code() == 404) {
} Toasty.info(context, context.getString(R.string.apiNotFound));
else if(issueState.equals("open")) {
Toasty.success(ctx, ctx.getString(R.string.issueStateReopened)); }
tinyDb.putString("issueState", "open"); else {
} Toasty.info(context, context.getString(R.string.genericError));
} }
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle), ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); }
} @Override
else if(response.code() == 403) { public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); }
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
public static void subscribe(final Context ctx) {
final TinyDB tinyDB = new TinyDB(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String[] repoFullName = tinyDB.getString("repoFullName").split("/");
if(repoFullName.length != 2) {
return;
}
final String userLogin = tinyDB.getString("userLogin");
final String token = "token " + tinyDB.getString(tinyDB.getString("loginUid") + "-token");
final int issueNr = Integer.parseInt(tinyDB.getString("issueNumber"));
Call<Void> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().addIssueSubscriber(token, repoFullName[0], repoFullName[1], issueNr, userLogin);
call.enqueue(new Callback<Void>() {
@Override
public void onResponse(@NonNull Call<Void> call, @NonNull retrofit2.Response<Void> response) {
if(response.isSuccessful()) {
if(response.code() == 201) {
Toasty.success(ctx, ctx.getString(R.string.subscribedSuccessfully));
tinyDB.putBoolean("issueSubscribed", true);
}
else if(response.code() == 200) {
tinyDB.putBoolean("issueSubscribed", true);
Toasty.success(ctx, ctx.getString(R.string.alreadySubscribed));
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle), ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.error(ctx, ctx.getString(R.string.subscriptionError));
}
}
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Toasty.success(ctx, ctx.getString(R.string.unsubscribedSuccessfully));
}
});
}
public static void unsubscribe(final Context ctx) {
final TinyDB tinyDB = new TinyDB(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String[] repoFullName = tinyDB.getString("repoFullName").split("/");
if(repoFullName.length != 2) {
return;
}
final String userLogin = tinyDB.getString("userLogin");
final String token = "token " + tinyDB.getString(tinyDB.getString("loginUid") + "-token");
final int issueNr = Integer.parseInt(tinyDB.getString("issueNumber"));
Call<Void> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().delIssueSubscriber(token, repoFullName[0], repoFullName[1], issueNr, userLogin);
call.enqueue(new Callback<Void>() {
@Override
public void onResponse(@NonNull Call<Void> call, @NonNull retrofit2.Response<Void> response) {
if(response.isSuccessful()) {
if(response.code() == 201) {
Toasty.success(ctx, ctx.getString(R.string.unsubscribedSuccessfully));
tinyDB.putBoolean("issueSubscribed", false);
}
else if(response.code() == 200) {
tinyDB.putBoolean("issueSubscribed", false);
Toasty.success(ctx, ctx.getString(R.string.alreadyUnsubscribed));
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle), ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.error(ctx, ctx.getString(R.string.unsubscriptionError));
}
}
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.unsubscriptionError));
}
});
}
} }

View File

@ -1,139 +0,0 @@
package org.mian.gitnex.actions;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Milestones;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class MilestoneActions {
static final private String TAG = "MilestoneActions : ";
public static void closeMilestone(final Context ctx, int milestoneId_) {
final TinyDB tinyDB = new TinyDB(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String loginUid = tinyDB.getString("loginUid");
final String token = "token " + tinyDB.getString(loginUid + "-token");
Milestones milestoneStateJson = new Milestones("closed");
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.closeReopenMilestone(token, repoOwner, repoName, milestoneId_, milestoneStateJson);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.isSuccessful()) {
Toasty.success(ctx, ctx.getString(R.string.milestoneStatusUpdate));
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle),
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
public static void openMilestone(final Context ctx, int milestoneId_) {
final TinyDB tinyDB = new TinyDB(ctx);
final String instanceUrl = tinyDB.getString("instanceUrl");
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String loginUid = tinyDB.getString("loginUid");
final String token = "token " + tinyDB.getString(loginUid + "-token");
Milestones milestoneStateJson = new Milestones("open");
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.closeReopenMilestone(token, repoOwner, repoName, milestoneId_, milestoneStateJson);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.isSuccessful()) {
Toasty.success(ctx, ctx.getString(R.string.milestoneStatusUpdate));
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle),
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
}

View File

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

View File

@ -8,8 +8,8 @@ import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -46,7 +46,7 @@ public class RepositoryActions {
if(response.code() == 204) { if(response.code() == 204) {
tinyDb.putBoolean("repoCreated", true); tinyDb.putBoolean("repoCreated", true);
Toasty.success(context, context.getString(R.string.starRepositorySuccess)); Toasty.info(context, context.getString(R.string.starRepositorySuccess));
} }
} }
@ -60,17 +60,17 @@ public class RepositoryActions {
} }
else if(response.code() == 403) { else if(response.code() == 403) {
Toasty.error(context, context.getString(R.string.authorizeError)); Toasty.info(context, context.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
Toasty.warning(context, context.getString(R.string.apiNotFound)); Toasty.info(context, context.getString(R.string.apiNotFound));
} }
else { else {
Toasty.error(context, context.getString(R.string.genericError)); Toasty.info(context, context.getString(R.string.genericError));
} }
@ -111,7 +111,7 @@ public class RepositoryActions {
if(response.code() == 204) { if(response.code() == 204) {
tinyDb.putBoolean("repoCreated", true); tinyDb.putBoolean("repoCreated", true);
Toasty.success(context, context.getString(R.string.unStarRepositorySuccess)); Toasty.info(context, context.getString(R.string.unStarRepositorySuccess));
} }
} }
@ -125,17 +125,17 @@ public class RepositoryActions {
} }
else if(response.code() == 403) { else if(response.code() == 403) {
Toasty.error(context, context.getString(R.string.authorizeError)); Toasty.info(context, context.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
Toasty.warning(context, context.getString(R.string.apiNotFound)); Toasty.info(context, context.getString(R.string.apiNotFound));
} }
else { else {
Toasty.error(context, context.getString(R.string.genericError)); Toasty.info(context, context.getString(R.string.genericError));
} }
@ -176,7 +176,7 @@ public class RepositoryActions {
if(response.code() == 200) { if(response.code() == 200) {
tinyDb.putBoolean("repoCreated", true); tinyDb.putBoolean("repoCreated", true);
Toasty.success(context, context.getString(R.string.watchRepositorySuccess)); Toasty.info(context, context.getString(R.string.watchRepositorySuccess));
} }
} }
@ -190,17 +190,17 @@ public class RepositoryActions {
} }
else if(response.code() == 403) { else if(response.code() == 403) {
Toasty.error(context, context.getString(R.string.authorizeError)); Toasty.info(context, context.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
Toasty.warning(context, context.getString(R.string.apiNotFound)); Toasty.info(context, context.getString(R.string.apiNotFound));
} }
else { else {
Toasty.error(context, context.getString(R.string.genericError)); Toasty.info(context, context.getString(R.string.genericError));
} }
@ -240,7 +240,7 @@ public class RepositoryActions {
if(response.code() == 204) { if(response.code() == 204) {
tinyDb.putBoolean("repoCreated", true); tinyDb.putBoolean("repoCreated", true);
Toasty.success(context, context.getString(R.string.unWatchRepositorySuccess)); Toasty.info(context, context.getString(R.string.unWatchRepositorySuccess));
} }
else if(response.code() == 401) { else if(response.code() == 401) {
@ -253,17 +253,17 @@ public class RepositoryActions {
} }
else if(response.code() == 403) { else if(response.code() == 403) {
Toasty.error(context, context.getString(R.string.authorizeError)); Toasty.info(context, context.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
Toasty.warning(context, context.getString(R.string.apiNotFound)); Toasty.info(context, context.getString(R.string.apiNotFound));
} }
else { else {
Toasty.error(context, context.getString(R.string.genericError)); Toasty.info(context, context.getString(R.string.genericError));
} }

View File

@ -1,154 +0,0 @@
package org.mian.gitnex.actions;
import android.content.Context;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.AddNewTeamMemberActivity;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class TeamActions {
public static void removeTeamMember(final Context context, String userName, int teamId) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.removeTeamMember(Authorization.returnAuthentication(context, loginUid, instanceToken), teamId, userName);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.isSuccessful()) {
if(response.code() == 204) {
tinyDb.putBoolean("teamActionFlag", true);
Toasty.success(context, context.getString(R.string.memberRemovedMessage));
((AddNewTeamMemberActivity)context).finish();
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle),
context.getResources().getString(R.string.alertDialogTokenRevokedMessage),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.error(context, context.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Toasty.error(context, context.getResources().getString(R.string.genericServerResponseError));
}
});
}
public static void addTeamMember(final Context context, String userName, int teamId) {
final TinyDB tinyDb = new TinyDB(context);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.addTeamMember(Authorization.returnAuthentication(context, loginUid, instanceToken), teamId, userName);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.isSuccessful()) {
if(response.code() == 204) {
tinyDb.putBoolean("teamActionFlag", true);
Toasty.success(context, context.getString(R.string.memberAddedMessage));
((AddNewTeamMemberActivity)context).finish();
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle),
context.getResources().getString(R.string.alertDialogTokenRevokedMessage),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.error(context, context.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(context, context.getString(R.string.apiNotFound));
}
else {
Toasty.error(context, context.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Toasty.error(context, context.getResources().getString(R.string.genericServerResponseError));
}
});
}
}

View File

@ -1,39 +1,40 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.adapters.UserSearchAdapter; import org.mian.gitnex.adapters.UserSearchAdapter;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.models.UserSearch; import org.mian.gitnex.models.UserSearch;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import java.util.List; import java.util.List;
import retrofit2.Call; import java.util.Objects;
import retrofit2.Callback;
import retrofit2.Response;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class AddCollaboratorToRepositoryActivity extends BaseActivity { public class AddCollaboratorToRepositoryActivity extends AppCompatActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
private TextView addCollaboratorSearch; private TextView addCollaboratorSearch;
private TextView noData; private TextView noData;
private ProgressBar mProgressBar; private ProgressBar mProgressBar;
@ -41,19 +42,11 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
private RecyclerView mRecyclerView; private RecyclerView mRecyclerView;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_add_collaborator_to_repository;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_add_collaborator_to_repository);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); TinyDB tinyDb = new TinyDB(getApplicationContext());
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");
String repoFullName = tinyDb.getString("repoFullName"); String repoFullName = tinyDb.getString("repoFullName");
@ -66,33 +59,29 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
mProgressBar = findViewById(R.id.progress_bar); mProgressBar = findViewById(R.id.progress_bar);
noData = findViewById(R.id.noData); noData = findViewById(R.id.noData);
addCollaboratorSearch.requestFocus();
assert imm != null;
imm.showSoftInput(addCollaboratorSearch, InputMethodManager.SHOW_IMPLICIT);
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
addCollaboratorSearch.setOnEditorActionListener((v, actionId, event) -> { addCollaboratorSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
if (actionId == EditorInfo.IME_ACTION_SEND) { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(!addCollaboratorSearch.getText().toString().equals("")) { if (actionId == EditorInfo.IME_ACTION_SEND) {
loadUserSearchList(instanceUrl, instanceToken, addCollaboratorSearch.getText().toString(), loginUid); if(!addCollaboratorSearch.getText().toString().equals("")) {
loadUserSearchList(instanceUrl, instanceToken, addCollaboratorSearch.getText().toString(), getApplicationContext(), loginUid);
}
} }
return false;
} }
return false;
}); });
} }
public void loadUserSearchList(String instanceUrl, String token, String searchKeyword, String loginUid) { public void loadUserSearchList(String instanceUrl, String token, String searchKeyword, final Context context, String loginUid) {
Call<UserSearch> call = RetrofitClient Call<UserSearch> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getUserBySearch(Authorization.returnAuthentication(ctx, loginUid, token), searchKeyword, 10); .getUserBySearch(Authorization.returnAuthentication(getApplicationContext(), loginUid, token), searchKeyword, 10);
call.enqueue(new Callback<UserSearch>() { call.enqueue(new Callback<UserSearch>() {
@ -101,7 +90,7 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
if (response.isSuccessful()) { if (response.isSuccessful()) {
assert response.body() != null; assert response.body() != null;
getUsersList(response.body().getData(), ctx); getUsersList(response.body().getData(), context);
} else { } else {
Log.i("onResponse", String.valueOf(response.code())); Log.i("onResponse", String.valueOf(response.code()));
} }
@ -121,7 +110,7 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
UserSearchAdapter adapter = new UserSearchAdapter(dataList, context); UserSearchAdapter adapter = new UserSearchAdapter(dataList, context);
mRecyclerView.setHasFixedSize(true); mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(ctx)); mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL); DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration); mRecyclerView.addItemDecoration(dividerItemDecoration);
@ -141,7 +130,12 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
} }
private void initCloseListener() { private void initCloseListener() {
onClickListener = view -> finish(); onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
} }

View File

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

View File

@ -1,170 +0,0 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.UserSearchForTeamMemberAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.models.UserSearch;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class AddNewTeamMemberActivity extends BaseActivity {
private View.OnClickListener onClickListener;
final Context ctx = this;
private Context appCtx;
private TextView addNewTeamMember;
private TextView noData;
private ProgressBar mProgressBar;
private RecyclerView mRecyclerView;
private List<UserInfo> dataList;
private UserSearchForTeamMemberAdapter adapter;
private String teamId;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_add_new_team_member;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
addNewTeamMember = findViewById(R.id.addNewTeamMember);
mRecyclerView = findViewById(R.id.recyclerViewUserSearch);
mProgressBar = findViewById(R.id.progress_bar);
noData = findViewById(R.id.noData);
addNewTeamMember.requestFocus();
assert imm != null;
imm.showSoftInput(addNewTeamMember, InputMethodManager.SHOW_IMPLICIT);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(getIntent().getStringExtra("teamId") != null && !Objects.requireNonNull(getIntent().getStringExtra("teamId")).equals("")) {
teamId = getIntent().getStringExtra("teamId");
}
else {
teamId = "0";
}
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(ctx));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
dataList = new ArrayList<>();
addNewTeamMember.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(!addNewTeamMember.getText().toString().equals("") && addNewTeamMember.getText().toString().length() > 1) {
adapter = new UserSearchForTeamMemberAdapter(dataList, ctx, Integer.parseInt(teamId));
loadUserSearchList(instanceUrl, instanceToken, addNewTeamMember.getText().toString(), loginUid, teamId);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
public void loadUserSearchList(String instanceUrl, String token, String searchKeyword, String loginUid, String teamId) {
Call<UserSearch> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserBySearch(Authorization.returnAuthentication(ctx, loginUid, token), searchKeyword, 10);
mProgressBar.setVisibility(View.VISIBLE);
call.enqueue(new Callback<UserSearch>() {
@Override
public void onResponse(@NonNull Call<UserSearch> call, @NonNull Response<UserSearch> response) {
if(response.isSuccessful()) {
assert response.body() != null;
if(response.body().getData().size() > 0) {
dataList.clear();
dataList.addAll(response.body().getData());
mRecyclerView.setAdapter(adapter);
noData.setVisibility(View.GONE);
mProgressBar.setVisibility(View.GONE);
}
else {
noData.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
}
}
@Override
public void onFailure(@NonNull Call<UserSearch> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -1,23 +1,25 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import android.view.Window;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.MultiSelectDialog; import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators; import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues; import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.MultiSelectModel; import org.mian.gitnex.models.MultiSelectModel;
import org.mian.gitnex.models.UpdateIssueAssignees; import org.mian.gitnex.models.UpdateIssueAssignee;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import retrofit2.Call; import retrofit2.Call;
@ -27,30 +29,24 @@ import retrofit2.Callback;
* Author M M Arif * Author M M Arif
*/ */
public class AddRemoveAssigneesActivity extends BaseActivity { public class AddRemoveAssigneesActivity extends AppCompatActivity {
private ArrayList<MultiSelectModel> listOfCollaborators = new ArrayList<>(); private ArrayList<MultiSelectModel> listOfCollaborators = new ArrayList<>();
private ArrayList<Integer> issueAssigneesIds = new ArrayList<>(); private ArrayList<Integer> issueAssigneesIds = new ArrayList<>();
private Boolean assigneesFlag = false; private Boolean assigneesFlag = false;
private MultiSelectDialog multiSelectDialogAssignees; private MultiSelectDialog multiSelectDialogAssignees;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_add_remove_assignees;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
//supportRequestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_add_remove_assignees);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT)); getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid"); final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName"); String repoFullName = tinyDb.getString("repoFullName");
@ -66,12 +62,12 @@ public class AddRemoveAssigneesActivity extends BaseActivity {
private void getAssignees(final String instanceUrl, final String instanceToken, final String repoOwner, final String repoName, final int issueIndex, final String loginUid) { private void getAssignees(final String instanceUrl, final String instanceToken, final String repoOwner, final String repoName, final int issueIndex, final String loginUid) {
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<List<Collaborators>> call = RetrofitClient Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName); .getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() { call.enqueue(new Callback<List<Collaborators>>() {
@ -94,9 +90,9 @@ public class AddRemoveAssigneesActivity extends BaseActivity {
// get current issue assignees // get current issue assignees
Call<Issues> callSingleIssueAssignees = RetrofitClient Call<Issues> callSingleIssueAssignees = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex); .getIssueByIndex(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
callSingleIssueAssignees.enqueue(new Callback<Issues>() { callSingleIssueAssignees.enqueue(new Callback<Issues>() {
@ -139,11 +135,11 @@ public class AddRemoveAssigneesActivity extends BaseActivity {
.multiSelectList(listOfCollaborators) .multiSelectList(listOfCollaborators)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() { .onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override @Override
public void onSelected(List<Integer> selectedIds, List<String> selectedNames, String dataString) { public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
Log.i("selectedNames", String.valueOf(selectedNames)); Log.i("selectedNames", String.valueOf(selectedNames));
updateIssueAssignees(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, loginUid, issueIndex, selectedNames); updateIssueAssignees(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, loginUid, issueIndex, selectedNames);
tinyDb.putBoolean("singleIssueUpdate", true); tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity(); CloseActivity();
} }
@ -167,9 +163,9 @@ public class AddRemoveAssigneesActivity extends BaseActivity {
.multiSelectList(listOfCollaborators) .multiSelectList(listOfCollaborators)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() { .onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override @Override
public void onSelected(List<Integer> selectedIds, List<String> selectedNames, String dataString) { public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
updateIssueAssignees(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, loginUid, issueIndex, selectedNames); updateIssueAssignees(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, loginUid, issueIndex, selectedNames);
tinyDb.putBoolean("singleIssueUpdate", true); tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity(); CloseActivity();
@ -207,17 +203,17 @@ public class AddRemoveAssigneesActivity extends BaseActivity {
} }
else if(response.code() == 403) { else if(response.code() == 403) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); Toasty.info(ctx, ctx.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)); Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
} }
else { else {
Toasty.error(ctx, getString(R.string.genericError)); Toasty.info(getApplicationContext(), getString(R.string.genericError));
} }
} }
@ -238,14 +234,14 @@ public class AddRemoveAssigneesActivity extends BaseActivity {
private void updateIssueAssignees(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String loginUid, int issueIndex, List<String> issueAssigneesList) { private void updateIssueAssignees(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String loginUid, int issueIndex, List<String> issueAssigneesList) {
UpdateIssueAssignees updateAssigneeJson = new UpdateIssueAssignees(issueAssigneesList); UpdateIssueAssignee updateAssigneeJson = new UpdateIssueAssignee(issueAssigneesList);
Call<JsonElement> call3; Call<JsonElement> call3;
call3 = RetrofitClient call3 = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.patchIssueAssignees(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, updateAssigneeJson); .patchIssueAssignee(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, updateAssigneeJson);
call3.enqueue(new Callback<JsonElement>() { call3.enqueue(new Callback<JsonElement>() {
@ -254,7 +250,7 @@ public class AddRemoveAssigneesActivity extends BaseActivity {
if(response2.code() == 201) { if(response2.code() == 201) {
Toasty.success(ctx, ctx.getString(R.string.assigneesUpdated)); Toasty.info(ctx, ctx.getString(R.string.assigneesUpdated));
} }
else if(response2.code() == 401) { else if(response2.code() == 401) {
@ -267,17 +263,17 @@ public class AddRemoveAssigneesActivity extends BaseActivity {
} }
else if(response2.code() == 403) { else if(response2.code() == 403) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); Toasty.info(ctx, ctx.getString(R.string.authorizeError));
} }
else if(response2.code() == 404) { else if(response2.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)); Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
} }
else { else {
Toasty.error(ctx, getString(R.string.genericError)); Toasty.info(getApplicationContext(), getString(R.string.genericError));
} }

View File

@ -1,54 +1,49 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import android.view.Window;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.MultiSelectDialog; import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Labels; import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.MultiSelectModel; import org.mian.gitnex.models.MultiSelectModel;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class AddRemoveLabelsActivity extends BaseActivity { public class AddRemoveLabelsActivity extends AppCompatActivity {
private ArrayList<MultiSelectModel> listOfLabels = new ArrayList<>(); private ArrayList<MultiSelectModel> listOfLabels = new ArrayList<>();
private ArrayList<Integer> issueLabelIds = new ArrayList<>(); private ArrayList<Integer> issueLabelIds = new ArrayList<>();
private Boolean labelsFlag = false; private Boolean labelsFlag = false;
private MultiSelectDialog multiSelectDialogLabels; private MultiSelectDialog multiSelectDialogLabels;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_add_remove_labels;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
//supportRequestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_add_remove_labels);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT)); getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid"); final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName"); String repoFullName = tinyDb.getString("repoFullName");
@ -64,12 +59,12 @@ public class AddRemoveLabelsActivity extends BaseActivity {
private void getLabels(final String instanceUrl, final String instanceToken, final String repoOwner, final String repoName, final int issueIndex, final String loginUid) { private void getLabels(final String instanceUrl, final String instanceToken, final String repoOwner, final String repoName, final int issueIndex, final String loginUid) {
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<List<Labels>> call = RetrofitClient Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getlabels(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName); .getlabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Labels>>() { call.enqueue(new Callback<List<Labels>>() {
@ -92,9 +87,9 @@ public class AddRemoveLabelsActivity extends BaseActivity {
// get current issue labels // get current issue labels
Call<List<Labels>> callSingleIssueLabels = RetrofitClient Call<List<Labels>> callSingleIssueLabels = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getIssueLabels(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex); .getIssueLabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
callSingleIssueLabels.enqueue(new Callback<List<Labels>>() { callSingleIssueLabels.enqueue(new Callback<List<Labels>>() {
@ -128,7 +123,7 @@ public class AddRemoveLabelsActivity extends BaseActivity {
.multiSelectList(listOfLabels) .multiSelectList(listOfLabels)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() { .onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override @Override
public void onSelected(List<Integer> selectedIds, List<String> selectedNames, String dataString) { public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
String labelIds = selectedIds.toString(); String labelIds = selectedIds.toString();
int[] integers; int[] integers;
@ -145,7 +140,7 @@ public class AddRemoveLabelsActivity extends BaseActivity {
integers = new int[0]; integers = new int[0];
} }
updateIssueLabels(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, integers, loginUid); updateIssueLabels(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, integers, loginUid);
tinyDb.putBoolean("singleIssueUpdate", true); tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity(); CloseActivity();
} }
@ -169,7 +164,7 @@ public class AddRemoveLabelsActivity extends BaseActivity {
.multiSelectList(listOfLabels) .multiSelectList(listOfLabels)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() { .onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override @Override
public void onSelected(List<Integer> selectedIds, List<String> selectedNames, String dataString) { public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
String labelIds = selectedIds.toString(); String labelIds = selectedIds.toString();
int[] integers; int[] integers;
@ -186,7 +181,7 @@ public class AddRemoveLabelsActivity extends BaseActivity {
integers = new int[0]; integers = new int[0];
} }
updateIssueLabels(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, integers, loginUid); updateIssueLabels(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, integers, loginUid);
tinyDb.putBoolean("singleIssueUpdate", true); tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity(); CloseActivity();
@ -224,17 +219,17 @@ public class AddRemoveLabelsActivity extends BaseActivity {
} }
else if(response.code() == 403) { else if(response.code() == 403) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); Toasty.info(ctx, ctx.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)); Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
} }
else { else {
Toasty.error(ctx, getString(R.string.genericError)); Toasty.info(getApplicationContext(), getString(R.string.genericError));
} }
} }
@ -254,9 +249,9 @@ public class AddRemoveLabelsActivity extends BaseActivity {
Labels patchIssueLabels = new Labels(issueLabels); Labels patchIssueLabels = new Labels(issueLabels);
Call<JsonElement> call = RetrofitClient Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.updateIssueLabels(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, patchIssueLabels); .updateIssueLabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, patchIssueLabels);
call.enqueue(new Callback<JsonElement>() { call.enqueue(new Callback<JsonElement>() {
@ -265,7 +260,7 @@ public class AddRemoveLabelsActivity extends BaseActivity {
if(response.code() == 200) { if(response.code() == 200) {
Toasty.success(ctx, ctx.getString(R.string.labelsUpdated)); Toasty.info(ctx, ctx.getString(R.string.labelsUpdated));
} }
else if(response.code() == 401) { else if(response.code() == 401) {
@ -278,17 +273,17 @@ public class AddRemoveLabelsActivity extends BaseActivity {
} }
else if(response.code() == 403) { else if(response.code() == 403) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); Toasty.info(ctx, ctx.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)); Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
} }
else { else {
Toasty.error(ctx, getString(R.string.genericError)); Toasty.info(getApplicationContext(), getString(R.string.genericError));
} }

View File

@ -1,5 +1,14 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
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;
@ -11,47 +20,37 @@ 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.AdminUsersBottomSheetFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil;
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
*/ */
public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAdminUsersFragment.BottomSheetListener { public class AdminGetUsersActivity extends AppCompatActivity implements AdminUsersBottomSheetFragment.BottomSheetListener {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
private AdminGetUsersAdapter adapter; private AdminGetUsersAdapter adapter;
private RecyclerView mRecyclerView; private RecyclerView mRecyclerView;
private TextView noDataUsers; private TextView noDataUsers;
private Boolean searchFilter = false; private Boolean searchFilter = false;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_admin_get_users;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_admin_get_users);
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
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");
@ -69,43 +68,50 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
mRecyclerView.setHasFixedSize(true); mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(ctx)); mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL); DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration); mRecyclerView.addItemDecoration(dividerItemDecoration);
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> { swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
AdminGetUsersViewModel.loadUsersList(getApplicationContext(), instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken));
}
}, 500);
}
});
swipeRefresh.setRefreshing(false); fetchDataAsync(getApplicationContext(), instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken));
AdminGetUsersViewModel.loadUsersList(ctx, instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken));
}, 500));
fetchDataAsync(ctx, instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken));
} }
private void fetchDataAsync(Context ctx, String instanceUrl, String instanceToken) { private void fetchDataAsync(Context ctx, String instanceUrl, String instanceToken) {
AdminGetUsersViewModel usersModel = new ViewModelProvider(this).get(AdminGetUsersViewModel.class); AdminGetUsersViewModel usersModel = ViewModelProviders.of(this).get(AdminGetUsersViewModel.class);
usersModel.getUsersList(ctx, instanceUrl, instanceToken).observe(this, usersListMain -> { usersModel.getUsersList(ctx, instanceUrl, instanceToken).observe(this, new Observer<List<UserInfo>>() {
@Override
adapter = new AdminGetUsersAdapter(ctx, usersListMain); public void onChanged(@Nullable List<UserInfo> usersListMain) {
if(adapter.getItemCount() > 0) { adapter = new AdminGetUsersAdapter(getApplicationContext(), usersListMain);
mRecyclerView.setVisibility(View.VISIBLE); if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter); mRecyclerView.setVisibility(View.VISIBLE);
noDataUsers.setVisibility(View.GONE); mRecyclerView.setAdapter(adapter);
searchFilter = true; noDataUsers.setVisibility(View.GONE);
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);
}
}); });
} }
@ -116,36 +122,37 @@ 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 Handler().postDelayed(new Runnable() {
@Override
public void run() {
if(searchFilter) {
if(searchFilter) { boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getApplicationContext()));
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); inflater.inflate(R.menu.search_menu, menu);
inflater.inflate(R.menu.search_menu, menu); MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
MenuItem searchItem = menu.findItem(R.id.action_search); if(!connToInternet) {
SearchView searchView = (SearchView) searchItem.getActionView(); return;
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;
@ -161,7 +168,7 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
finish(); finish();
return true; return true;
case R.id.genericMenu: case R.id.genericMenu:
BottomSheetAdminUsersFragment bottomSheet = new BottomSheetAdminUsersFragment(); AdminUsersBottomSheetFragment bottomSheet = new AdminUsersBottomSheetFragment();
bottomSheet.show(getSupportFragmentManager(), "usersBottomSheet"); bottomSheet.show(getSupportFragmentManager(), "usersBottomSheet");
return true; return true;
default: default:
@ -182,7 +189,12 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
} }
private void initCloseListener() { private void initCloseListener() {
onClickListener = view -> finish(); onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
} }
} }

View File

@ -1,157 +0,0 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import org.acra.ACRA;
import org.acra.BuildConfig;
import org.acra.annotation.AcraNotification;
import org.acra.config.CoreConfigurationBuilder;
import org.acra.config.LimiterConfigurationBuilder;
import org.acra.config.MailSenderConfigurationBuilder;
import org.acra.data.StringFormat;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.FontsOverride;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.notifications.NotificationsMaster;
/**
* Author M M Arif
*/
@AcraNotification(resIcon = R.drawable.gitnex_transparent,
resTitle = R.string.crashTitle,
resChannelName = R.string.setCrashReports,
resText = R.string.crashMessage)
public abstract class BaseActivity extends AppCompatActivity {
private Context appCtx;
@Override
public void onCreate(Bundle savedInstanceState) {
appCtx = getApplicationContext();
final TinyDB tinyDb = new TinyDB(appCtx);
switch(tinyDb.getInt("themeId")) {
case 1:
setTheme(R.style.AppThemeLight);
break;
case 2:
if(TimeHelper.timeBetweenHours(18, 6)) { // 6pm to 6am
setTheme(R.style.AppTheme);
}
else {
setTheme(R.style.AppThemeLight);
}
break;
case 3:
setTheme(R.style.AppThemeRetro);
break;
case 4:
if(TimeHelper.timeBetweenHours(18, 6)) { // 6pm to 6am
setTheme(R.style.AppTheme);
}
else {
setTheme(R.style.AppThemeRetro);
}
break;
default:
setTheme(R.style.AppTheme);
break;
}
String appLocale = tinyDb.getString("locale");
AppUtil.setAppLocale(getResources(), appLocale);
super.onCreate(savedInstanceState);
setContentView(getLayoutResourceId());
switch(tinyDb.getInt("customFontId", -1)) {
case 0:
FontsOverride.setDefaultFont(this, "DEFAULT", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "fonts/roboto.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "fonts/roboto.ttf");
break;
case 2:
FontsOverride.setDefaultFont(this, "DEFAULT", "fonts/sourcecodeproregular.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "fonts/sourcecodeproregular.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "fonts/sourcecodeproregular.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "fonts/sourcecodeproregular.ttf");
break;
default:
FontsOverride.setDefaultFont(this, "DEFAULT", "fonts/manroperegular.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "fonts/manroperegular.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "fonts/manroperegular.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "fonts/manroperegular.ttf");
break;
}
if(tinyDb.getInt("pollingDelayMinutes") == 0) {
tinyDb.putInt("pollingDelayMinutes", 15);
}
NotificationsMaster.hireWorker(appCtx);
// enabling counter badges by default
if(tinyDb.getString("enableCounterBadgesInit").isEmpty()) {
tinyDb.putBoolean("enableCounterBadges", true);
tinyDb.putString("enableCounterBadgesInit", "yes");
}
// enable crash reports by default
if(tinyDb.getString("crashReportingEnabledInit").isEmpty()) {
tinyDb.putBoolean("crashReportingEnabled", true);
tinyDb.putString("crashReportingEnabledInit", "yes");
}
// default cache setter
if(tinyDb.getString("cacheSizeStr").isEmpty()) {
tinyDb.putString("cacheSizeStr", getResources().getString(R.string.cacheSizeDataSelectionSelectedText));
}
if(tinyDb.getString("cacheSizeImagesStr").isEmpty()) {
tinyDb.putString("cacheSizeImagesStr", getResources().getString(R.string.cacheSizeImagesSelectionSelectedText));
}
// enable comment drafts by default
if(tinyDb.getString("draftsCommentsDeletionEnabledInit").isEmpty()) {
tinyDb.putBoolean("draftsCommentsDeletionEnabled", true);
tinyDb.putString("draftsCommentsDeletionEnabledInit", "yes");
}
if(!tinyDb.getString("instanceUrlWithProtocol").endsWith("/")) {
tinyDb.putString("instanceUrlWithProtocol", tinyDb.getString("instanceUrlWithProtocol") + "/");
}
if (tinyDb.getBoolean("crashReportingEnabled")) {
CoreConfigurationBuilder ACRABuilder = new CoreConfigurationBuilder(this);
ACRABuilder.setBuildConfigClass(BuildConfig.class).setReportFormat(StringFormat.KEY_VALUE_LIST);
ACRABuilder.getPluginConfigurationBuilder(MailSenderConfigurationBuilder.class).setReportAsFile(true).setMailTo(getResources().getString(R.string.appEmail)).setSubject(getResources().getString(R.string.crashReportEmailSubject, AppUtil.getAppBuildNo(getApplicationContext()))).setEnabled(true);
ACRABuilder.getPluginConfigurationBuilder(LimiterConfigurationBuilder.class).setEnabled(true);
ACRA.init(getApplication(), ACRABuilder);
}
}
protected abstract int getLayoutResourceId();
}

View File

@ -1,284 +0,0 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.CommitsAdapter;
import org.mian.gitnex.clients.AppApiService;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.interfaces.ApiInterface;
import org.mian.gitnex.models.Commits;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class CommitsActivity extends BaseActivity {
final Context ctx = this;
private Context appCtx;
private View.OnClickListener onClickListener;
private TextView noData;
private ProgressBar progressBar;
private String TAG = "CommitsActivity";
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int pageSize = 1;
private RecyclerView recyclerView;
private List<Commits> commitsList;
private CommitsAdapter adapter;
private ApiInterface api;
private ProgressBar progressLoadMore;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_commits;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
String branchName = getIntent().getStringExtra("branchName");
TextView toolbar_title = findViewById(R.id.toolbar_title);
toolbar_title.setMovementMethod(new ScrollingMovementMethod());
toolbar_title.setText(branchName);
ImageView closeActivity = findViewById(R.id.close);
noData = findViewById(R.id.noDataCommits);
progressLoadMore = findViewById(R.id.progressLoadMore);
progressBar = findViewById(R.id.progress_bar);
SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
// if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances)
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
}
recyclerView = findViewById(R.id.recyclerView);
commitsList = new ArrayList<>();
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setRefreshing(false);
loadInitial(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName, resultLimit);
adapter.notifyDataChanged();
}, 200));
adapter = new CommitsAdapter(ctx, commitsList);
adapter.setLoadMoreListener(() -> recyclerView.post(() -> {
if(commitsList.size() == resultLimit || pageSize == resultLimit) {
int page = (commitsList.size() + resultLimit) / resultLimit;
loadMore(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, page, branchName, resultLimit);
}
}));
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
recyclerView.setAdapter(adapter);
api = AppApiService.createService(ApiInterface.class, instanceUrl, ctx);
loadInitial(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName, resultLimit);
}
private void loadInitial(String token, String repoOwner, String repoName, String branchName, int resultLimit) {
Call<List<Commits>> call = api.getRepositoryCommits(token, repoOwner, repoName, 1, branchName, resultLimit);
call.enqueue(new Callback<List<Commits>>() {
@Override
public void onResponse(@NonNull Call<List<Commits>> call, @NonNull Response<List<Commits>> response) {
if(response.isSuccessful()) {
assert response.body() != null;
if(response.body().size() > 0) {
commitsList.clear();
commitsList.addAll(response.body());
adapter.notifyDataChanged();
noData.setVisibility(View.GONE);
}
else {
commitsList.clear();
adapter.notifyDataChanged();
noData.setVisibility(View.VISIBLE);
}
progressBar.setVisibility(View.GONE);
}
else {
Log.e(TAG, String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Commits>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
private void loadMore(String token, String repoOwner, String repoName, final int page, String branchName, int resultLimit) {
progressLoadMore.setVisibility(View.VISIBLE);
Call<List<Commits>> call = api.getRepositoryCommits(token, repoOwner, repoName, page, branchName, resultLimit);
call.enqueue(new Callback<List<Commits>>() {
@Override
public void onResponse(@NonNull Call<List<Commits>> call, @NonNull Response<List<Commits>> response) {
if(response.isSuccessful()) {
List<Commits> result = response.body();
assert result != null;
if(result.size() > 0) {
pageSize = result.size();
commitsList.addAll(result);
}
else {
adapter.setMoreDataAvailable(false);
}
adapter.notifyDataChanged();
progressLoadMore.setVisibility(View.GONE);
}
else {
Log.e(TAG, String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Commits>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search_menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
filter(newText);
return true;
}
});
return super.onCreateOptionsMenu(menu);
}
private void filter(String text) {
List<Commits> arr = new ArrayList<>();
for(Commits d : commitsList) {
if(d.getCommit().getMessage().toLowerCase().contains(text) || d.getSha().toLowerCase().contains(text)) {
arr.add(d);
}
}
adapter.updateList(arr);
}
private void initCloseListener() {
onClickListener = view -> {
getIntent().removeExtra("branchName");
finish();
};
}
}

View File

@ -1,535 +0,0 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.DeleteFile;
import org.mian.gitnex.models.EditFile;
import org.mian.gitnex.models.NewFile;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class CreateFileActivity extends BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
private Button newFileCreate;
private EditText newFileName;
private EditText newFileContent;
private EditText newFileBranchName;
private EditText newFileCommitMessage;
private Spinner newFileBranchesSpinner;
private String filePath;
private String fileSha;
private int fileAction = 0; // 0 = create, 1 = delete, 2 = edit
final Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
List<Branches> branchesList = new ArrayList<>();
@Override
protected int getLayoutResourceId(){
return R.layout.activity_new_file;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
closeActivity = findViewById(R.id.close);
newFileName = findViewById(R.id.newFileName);
newFileContent = findViewById(R.id.newFileContent);
newFileBranchName = findViewById(R.id.newFileBranchName);
newFileCommitMessage = findViewById(R.id.newFileCommitMessage);
TextView branchNameId = findViewById(R.id.branchNameId);
TextView branchNameHintText = findViewById(R.id.branchNameHintText);
TextView toolbarTitle = findViewById(R.id.toolbarTitle);
TextView fileNameHint = findViewById(R.id.fileNameHint);
newFileName.requestFocus();
assert imm != null;
imm.showSoftInput(newFileName, InputMethodManager.SHOW_IMPLICIT);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
newFileCreate = findViewById(R.id.newFileCreate);
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", 1) == 1) {
fileNameHint.setVisibility(View.GONE);
fileAction = getIntent().getIntExtra("fileAction", 1);
filePath = getIntent().getStringExtra("filePath");
String fileContents = getIntent().getStringExtra("fileContents");
fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.deleteFileText, filePath));
newFileCreate.setText(R.string.deleteFile);
newFileName.setText(filePath);
newFileName.setEnabled(false);
newFileName.setFocusable(false);
newFileContent.setText(fileContents);
newFileContent.setEnabled(false);
newFileContent.setFocusable(false);
}
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", 2) == 2) {
fileNameHint.setVisibility(View.GONE);
fileAction = getIntent().getIntExtra("fileAction", 2);
filePath = getIntent().getStringExtra("filePath");
String fileContents = getIntent().getStringExtra("fileContents");
fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.editFileText, filePath));
newFileCreate.setText(R.string.editFile);
newFileName.setText(filePath);
newFileName.setEnabled(false);
newFileName.setFocusable(false);
newFileContent.setText(fileContents);
}
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
newFileBranchesSpinner = findViewById(R.id.newFileBranchesSpinner);
getBranches(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
newFileBranchesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
public void onItemSelected(AdapterView<?> arg0,
View arg1, int arg2, long arg3)
{
Branches bModelValue = (Branches) newFileBranchesSpinner.getSelectedItem();
if(bModelValue.toString().equals("No branch")) {
newFileBranchName.setEnabled(true);
newFileBranchName.setVisibility(View.VISIBLE);
branchNameId.setVisibility(View.VISIBLE);
branchNameHintText.setVisibility(View.VISIBLE);
}
else {
newFileBranchName.setEnabled(false);
newFileBranchName.setVisibility(View.GONE);
branchNameId.setVisibility(View.GONE);
branchNameHintText.setVisibility(View.GONE);
newFileBranchName.setText("");
}
}
public void onNothingSelected(AdapterView<?> arg0) {}
});
disableProcessButton();
if(!connToInternet) {
newFileCreate.setEnabled(false);
}
else {
newFileCreate.setOnClickListener(createFileListener);
}
}
private View.OnClickListener createFileListener = v -> processNewFile();
private void processNewFile() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
String newFileName_ = newFileName.getText().toString();
String newFileContent_ = newFileContent.getText().toString();
String newFileBranchName_ = newFileBranchName.getText().toString();
String newFileCommitMessage_ = newFileCommitMessage.getText().toString();
Branches currentBranch = (Branches) newFileBranchesSpinner.getSelectedItem();
if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newFileName_.equals("") || newFileContent_.equals("") || newFileCommitMessage_.equals("")) {
Toasty.error(ctx, getString(R.string.newFileRequiredFields));
return;
}
if(currentBranch.toString().equals("No branch")) {
if(newFileBranchName_.equals("")) {
Toasty.error(ctx, getString(R.string.newFileRequiredFieldNewBranchName));
return;
}
else {
if(!appUtil.checkStringsWithDash(newFileBranchName_)) {
Toasty.error(ctx, getString(R.string.newFileInvalidBranchName));
return;
}
}
}
if(appUtil.charactersLength(newFileCommitMessage_) > 255) {
Toasty.warning(ctx, getString(R.string.newFileCommitMessageError));
}
else {
disableProcessButton();
if(fileAction == 1) {
deleteFile(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, filePath,
newFileBranchName_, newFileCommitMessage_, currentBranch.toString(), fileSha);
}
else if(fileAction == 2) {
editFile(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, filePath,
appUtil.encodeBase64(newFileContent_), newFileBranchName_, newFileCommitMessage_, currentBranch.toString(), fileSha);
}
else {
createNewFile(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, newFileName_,
appUtil.encodeBase64(newFileContent_), newFileBranchName_, newFileCommitMessage_, currentBranch.toString());
}
}
}
private void createNewFile(final String instanceUrl, final String token, String repoOwner, String repoName, String fileName, String fileContent, String fileBranchName, String fileCommitMessage, String currentBranch) {
NewFile createNewFileJsonStr;
if(currentBranch.equals("No branch")) {
createNewFileJsonStr = new NewFile("", fileContent, fileCommitMessage, fileBranchName);
}
else {
createNewFileJsonStr = new NewFile(currentBranch, fileContent, fileCommitMessage, "");
}
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.createNewFile(token, repoOwner, repoName, fileName, createNewFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 201) {
enableProcessButton();
Toasty.success(ctx, getString(R.string.newFileSuccessMessage));
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
if(response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.orgCreatedError));
}
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void deleteFile(final String instanceUrl, final String token, String repoOwner, String repoName, String fileName, String fileBranchName, String fileCommitMessage, String currentBranch, String fileSha) {
String branchName;
DeleteFile deleteFileJsonStr;
if(currentBranch.equals("No branch")) {
branchName = fileBranchName;
deleteFileJsonStr = new DeleteFile("", fileCommitMessage, fileBranchName, fileSha);
}
else {
branchName = currentBranch;
deleteFileJsonStr = new DeleteFile(currentBranch, fileCommitMessage, "", fileSha);
}
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.deleteFile(token, repoOwner, repoName, fileName, deleteFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 200) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.deleteFileMessage, branchName));
getIntent().removeExtra("filePath");
getIntent().removeExtra("fileSha");
getIntent().removeExtra("fileContents");
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
}
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void editFile(final String instanceUrl, final String token, String repoOwner, String repoName, String fileName, String fileContent, String fileBranchName, String fileCommitMessage, String currentBranch, String fileSha) {
String branchName;
EditFile editFileJsonStr;
if(currentBranch.equals("No branch")) {
branchName = fileBranchName;
editFileJsonStr = new EditFile("", fileCommitMessage, fileBranchName, fileSha, fileContent);
}
else {
branchName = currentBranch;
editFileJsonStr = new EditFile(currentBranch, fileCommitMessage, "", fileSha, fileContent);
}
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.editFile(token, repoOwner, repoName, fileName, editFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 200) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.editFileMessage, branchName));
getIntent().removeExtra("filePath");
getIntent().removeExtra("fileSha");
getIntent().removeExtra("fileContents");
tinyDb.putBoolean("fileModified", true);
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
}
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void getBranches(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getBranches(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Branches>>() {
@Override
public void onResponse(@NonNull Call<List<Branches>> call, @NonNull retrofit2.Response<List<Branches>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Branches> branchesList_ = response.body();
branchesList.add(new Branches("No branch"));
assert branchesList_ != null;
if(branchesList_.size() > 0) {
for (int i = 0; i < branchesList_.size(); i++) {
Branches data = new Branches(
branchesList_.get(i).getName()
);
branchesList.add(data);
}
}
ArrayAdapter<Branches> adapter = new ArrayAdapter<>(CreateFileActivity.this,
R.layout.spinner_item, branchesList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
newFileBranchesSpinner.setAdapter(adapter);
enableProcessButton();
}
}
}
@Override
public void onFailure(@NonNull Call<List<Branches>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void disableProcessButton() {
newFileCreate.setEnabled(false);
}
private void enableProcessButton() {
newFileCreate.setEnabled(true);
}
}

View File

@ -1,11 +1,17 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.app.DatePickerDialog; import android.app.DatePickerDialog;
import android.content.Context; import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.DatePicker; import android.widget.DatePicker;
@ -13,7 +19,6 @@ import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.hendraanggrian.appcompat.socialview.Mention; import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter; import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
@ -21,31 +26,27 @@ import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.MultiSelectDialog; import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Collaborators; import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.CreateIssue; import org.mian.gitnex.models.CreateIssue;
import org.mian.gitnex.models.Labels; import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.Milestones; import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.models.MultiSelectModel; import org.mian.gitnex.models.MultiSelectModel;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
import retrofit2.Call; import java.util.Objects;
import retrofit2.Callback;
import retrofit2.Response;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class CreateIssueActivity extends BaseActivity implements View.OnClickListener { public class CreateIssueActivity extends AppCompatActivity implements View.OnClickListener {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
MultiSelectDialog multiSelectDialog; MultiSelectDialog multiSelectDialog;
@ -61,8 +62,6 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private boolean assigneesFlag; private boolean assigneesFlag;
private boolean labelsFlag; private boolean labelsFlag;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
List<Milestones> milestonesList = new ArrayList<>(); List<Milestones> milestonesList = new ArrayList<>();
ArrayList<MultiSelectModel> listOfAssignees = new ArrayList<>(); ArrayList<MultiSelectModel> listOfAssignees = new ArrayList<>();
@ -70,35 +69,21 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private ArrayAdapter<Mention> defaultMentionAdapter; private ArrayAdapter<Mention> defaultMentionAdapter;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_create_issue;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_create_issue);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); TinyDB tinyDb = new TinyDB(getApplicationContext());
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");
final String loginFullName = tinyDb.getString("userFullname");
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 repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
}
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = findViewById(R.id.close);
assigneesList = findViewById(R.id.newIssueAssigneesList); assigneesList = findViewById(R.id.newIssueAssigneesList);
newIssueLabels = findViewById(R.id.newIssueLabels); newIssueLabels = findViewById(R.id.newIssueLabels);
@ -108,10 +93,6 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
newIssueDescription = findViewById(R.id.newIssueDescription); newIssueDescription = findViewById(R.id.newIssueDescription);
labelsIdHolder = findViewById(R.id.labelsIdHolder); labelsIdHolder = findViewById(R.id.labelsIdHolder);
newIssueTitle.requestFocus();
assert imm != null;
imm.showSoftInput(newIssueTitle, InputMethodManager.SHOW_IMPLICIT);
defaultMentionAdapter = new MentionArrayAdapter<>(this); defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList(); loadCollaboratorsList();
@ -125,28 +106,34 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
newIssueDueDate.setOnClickListener(this); newIssueDueDate.setOnClickListener(this);
newIssueMilestoneSpinner = findViewById(R.id.newIssueMilestoneSpinner); newIssueMilestoneSpinner = findViewById(R.id.newIssueMilestoneSpinner);
getMilestones(instanceUrl, instanceToken, repoOwner, repoName, loginUid, resultLimit); newIssueMilestoneSpinner.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
getMilestones(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
getLabels(instanceUrl, instanceToken, repoOwner, repoName, loginUid); getLabels(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
getCollaborators(instanceUrl, instanceToken, repoOwner, repoName, loginUid, loginFullName); getCollaborators(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
disableProcessButton(); disableProcessButton();
if(!connToInternet) { if(!connToInternet) {
createNewIssueButton.setEnabled(false); createNewIssueButton.setEnabled(false);
} GradientDrawable shape = new GradientDrawable();
else { shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewIssueButton.setBackground(shape);
} else {
createNewIssueButton.setOnClickListener(this); createNewIssueButton.setOnClickListener(this);
} }
} }
private void processNewIssue() { private void processNewIssue() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid"); final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName"); String repoFullName = tinyDb.getString("repoFullName");
@ -167,21 +154,21 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
if(!connToInternet) { if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return; return;
} }
if (newIssueTitleForm.equals("")) { if (newIssueTitleForm.equals("")) {
Toasty.error(ctx, getString(R.string.issueTitleEmpty)); Toasty.info(getApplicationContext(), getString(R.string.issueTitleEmpty));
return; return;
} }
/*if (newIssueDescriptionForm.equals("")) { /*if (newIssueDescriptionForm.equals("")) {
Toasty.error(ctx, getString(R.string.issueDescriptionEmpty)); Toasty.info(getApplicationContext(), getString(R.string.issueDescriptionEmpty));
return; return;
}*/ }*/
@ -220,7 +207,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
public void loadCollaboratorsList() { public void loadCollaboratorsList() {
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid"); final String loginUid = tinyDb.getString("loginUid");
@ -231,9 +218,9 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
final String repoName = parts[1]; final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName); .getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() { call.enqueue(new Callback<List<Collaborators>>() {
@ -275,9 +262,9 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
Call<JsonElement> call3; Call<JsonElement> call3;
call3 = RetrofitClient call3 = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.createNewIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, createNewIssueJson); .createNewIssue(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, createNewIssueJson);
call3.enqueue(new Callback<JsonElement>() { call3.enqueue(new Callback<JsonElement>() {
@ -288,10 +275,10 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
if(response2.code() == 201) { if(response2.code() == 201) {
//Log.i("isSuccessful1", String.valueOf(response2.body())); //Log.i("isSuccessful1", String.valueOf(response2.body()));
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("resumeIssues", true); tinyDb.putBoolean("resumeIssues", true);
Toasty.success(ctx, getString(R.string.issueCreated)); Toasty.info(getApplicationContext(), getString(R.string.issueCreated));
enableProcessButton(); enableProcessButton();
finish(); finish();
@ -309,7 +296,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
} }
else { else {
Toasty.error(ctx, getString(R.string.issueCreatedError)); Toasty.info(getApplicationContext(), getString(R.string.issueCreatedError));
enableProcessButton(); enableProcessButton();
//Log.i("isSuccessful2", String.valueOf(response2.body())); //Log.i("isSuccessful2", String.valueOf(response2.body()));
@ -327,17 +314,21 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
} }
private void initCloseListener() { private void initCloseListener() {
onClickListener = new View.OnClickListener() {
onClickListener = view -> finish(); @Override
public void onClick(View view) {
finish();
}
};
} }
private void getMilestones(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid, int resultLimit) { private void getMilestones(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
String msState = "open"; String msState = "open";
Call<List<Milestones>> call = RetrofitClient Call<List<Milestones>> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getMilestones(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, 1, resultLimit, msState); .getMilestones(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, msState);
call.enqueue(new Callback<List<Milestones>>() { call.enqueue(new Callback<List<Milestones>>() {
@ -366,7 +357,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
} }
} }
ArrayAdapter<Milestones> adapter = new ArrayAdapter<>(CreateIssueActivity.this, ArrayAdapter<Milestones> adapter = new ArrayAdapter<>(getApplicationContext(),
R.layout.spinner_item, milestonesList); R.layout.spinner_item, milestonesList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item); adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
@ -386,14 +377,12 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
} }
private void getCollaborators(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid, String loginFullName) { private void getCollaborators(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Collaborators>> call = RetrofitClient Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName); .getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
listOfAssignees.add(new MultiSelectModel(-1, loginFullName));
call.enqueue(new Callback<List<Collaborators>>() { call.enqueue(new Callback<List<Collaborators>>() {
@ -432,7 +421,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
.multiSelectList(listOfAssignees) .multiSelectList(listOfAssignees)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() { .onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override @Override
public void onSelected(List<Integer> selectedIds, List<String> selectedNames, String dataString) { public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
assigneesList.setText(dataString); assigneesList.setText(dataString);
@ -461,9 +450,9 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private void getLabels(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) { private void getLabels(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Labels>> call = RetrofitClient Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getlabels(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName); .getlabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Labels>>() { call.enqueue(new Callback<List<Labels>>() {
@ -495,7 +484,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
.multiSelectList(listOfLabels) .multiSelectList(listOfLabels)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() { .onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override @Override
public void onSelected(List<Integer> selectedIds, List<String> selectedNames, String dataString) { public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
newIssueLabels.setText(dataString.trim()); newIssueLabels.setText(dataString.trim());
labelsIdHolder.setText(selectedIds.toString()); labelsIdHolder.setText(selectedIds.toString());
@ -529,7 +518,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
multiSelectDialog.show(getSupportFragmentManager(), "multiSelectDialog"); multiSelectDialog.show(getSupportFragmentManager(), "multiSelectDialog");
} }
else { else {
Toasty.warning(ctx, getResources().getString(R.string.noAssigneesFound)); Toasty.info(getApplicationContext(), getResources().getString(R.string.noAssigneesFound));
} }
} }
else if (v == newIssueLabels) { else if (v == newIssueLabels) {
@ -537,7 +526,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
multiSelectDialogLabels.show(getSupportFragmentManager(), "multiSelectDialogLabels"); multiSelectDialogLabels.show(getSupportFragmentManager(), "multiSelectDialogLabels");
} }
else { else {
Toasty.warning(ctx, getResources().getString(R.string.noLabelsFound)); Toasty.info(getApplicationContext(), getResources().getString(R.string.noLabelsFound));
} }
} }
else if (v == newIssueDueDate) { else if (v == newIssueDueDate) {
@ -569,10 +558,20 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private void disableProcessButton() { private void disableProcessButton() {
createNewIssueButton.setEnabled(false); createNewIssueButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewIssueButton.setBackground(shape);
} }
private void enableProcessButton() { private void enableProcessButton() {
createNewIssueButton.setEnabled(true); createNewIssueButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createNewIssueButton.setBackground(shape);
} }
} }

View File

@ -1,61 +1,53 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import com.pes.androidmaterialcolorpickerdialog.ColorPicker; import com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import com.pes.androidmaterialcolorpickerdialog.ColorPickerCallback; import com.pes.androidmaterialcolorpickerdialog.ColorPickerCallback;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.CreateLabel; import org.mian.gitnex.models.CreateLabel;
import org.mian.gitnex.models.Labels; import org.mian.gitnex.models.Labels;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.LabelsViewModel; import org.mian.gitnex.viewmodels.LabelsViewModel;
import java.util.Objects; import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class CreateLabelActivity extends BaseActivity { public class CreateLabelActivity extends AppCompatActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private TextView colorPicker; private TextView colorPicker;
private EditText labelName; private EditText labelName;
private Button createLabelButton; private Button createLabelButton;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_create_label;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_create_label);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); final TinyDB tinyDb = new TinyDB(getApplicationContext());
final TinyDB tinyDb = new TinyDB(appCtx);
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];
@ -66,23 +58,19 @@ public class CreateLabelActivity extends BaseActivity {
if(getIntent().getStringExtra("labelAction") != null && Objects.requireNonNull(getIntent().getStringExtra("labelAction")).equals("delete")) { if(getIntent().getStringExtra("labelAction") != null && Objects.requireNonNull(getIntent().getStringExtra("labelAction")).equals("delete")) {
deleteLabel(instanceUrl, instanceToken, repoOwner, repoName, Integer.parseInt(Objects.requireNonNull(getIntent().getStringExtra("labelId"))), loginUid); deleteLabel(instanceUrl, instanceToken, repoOwner, repoName, Integer.valueOf(Objects.requireNonNull(getIntent().getStringExtra("labelId"))), loginUid);
finish(); finish();
return; return;
} }
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = findViewById(R.id.close);
colorPicker = findViewById(R.id.colorPicker); colorPicker = findViewById(R.id.colorPicker);
labelName = findViewById(R.id.labelName); labelName = findViewById(R.id.labelName);
createLabelButton = findViewById(R.id.createLabelButton); createLabelButton = findViewById(R.id.createLabelButton);
labelName.requestFocus();
assert imm != null;
imm.showSoftInput(labelName, InputMethodManager.SHOW_IMPLICIT);
final ColorPicker cp = new ColorPicker(CreateLabelActivity.this, 235, 113, 33); final ColorPicker cp = new ColorPicker(CreateLabelActivity.this, 235, 113, 33);
initCloseListener(); initCloseListener();
@ -117,28 +105,43 @@ public class CreateLabelActivity extends BaseActivity {
createLabelButton.setText(getResources().getString(R.string.newUpdateButtonCopy)); createLabelButton.setText(getResources().getString(R.string.newUpdateButtonCopy));
createLabelButton.setOnClickListener(updateLabelListener); createLabelButton.setOnClickListener(updateLabelListener);
return; return;
} }
if(!connToInternet) { if(!connToInternet) {
createLabelButton.setEnabled(false); createLabelButton.setEnabled(false);
} GradientDrawable shape = new GradientDrawable();
else { shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createLabelButton.setBackground(shape);
} else {
createLabelButton.setOnClickListener(createLabelListener); createLabelButton.setOnClickListener(createLabelListener);
} }
} }
private View.OnClickListener createLabelListener = v -> processCreateLabel(); private View.OnClickListener createLabelListener = new View.OnClickListener() {
public void onClick(View v) {
processCreateLabel();
}
};
private View.OnClickListener updateLabelListener = v -> processUpdateLabel(); private View.OnClickListener updateLabelListener = new View.OnClickListener() {
public void onClick(View v) {
processUpdateLabel();
}
};
private void processUpdateLabel() { private void processUpdateLabel() {
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(getApplicationContext());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
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("/");
@ -160,36 +163,35 @@ public class CreateLabelActivity extends BaseActivity {
if(!connToInternet) { if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return; return;
} }
if(updateLabelName.equals("")) { if(updateLabelName.equals("")) {
Toasty.error(ctx, getString(R.string.labelEmptyError)); Toasty.info(getApplicationContext(), getString(R.string.labelEmptyError));
return; return;
} }
if(!appUtil.checkStrings(updateLabelName)) { if(!appUtil.checkStrings(updateLabelName)) {
Toasty.error(ctx, getString(R.string.labelNameError)); Toasty.info(getApplicationContext(), getString(R.string.labelNameError));
return; return;
} }
disableProcessButton(); disableProcessButton();
patchLabel(instanceUrl, instanceToken, repoOwner, repoName, updateLabelName, updateLabelColor, Integer.parseInt( patchLabel(instanceUrl, instanceToken, repoOwner, repoName, updateLabelName, updateLabelColor, Integer.valueOf(getIntent().getStringExtra("labelId")), loginUid);
Objects.requireNonNull(getIntent().getStringExtra("labelId"))), loginUid);
} }
private void processCreateLabel() { private void processCreateLabel() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
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];
@ -201,7 +203,7 @@ public class CreateLabelActivity extends BaseActivity {
String newLabelName = labelName.getText().toString(); String newLabelName = labelName.getText().toString();
String newLabelColor; String newLabelColor;
if(tinyDb.getString("labelColor").isEmpty()) { if(tinyDb.getString("labelColor").isEmpty()) {
newLabelColor = String.format("#%06X", (0xFFFFFF & ContextCompat.getColor(ctx, R.color.releasePre))); newLabelColor = String.format("#%06X", (0xFFFFFF & ContextCompat.getColor(getApplicationContext(), R.color.releasePre)));
} }
else { else {
newLabelColor = tinyDb.getString("labelColor"); newLabelColor = tinyDb.getString("labelColor");
@ -209,21 +211,21 @@ public class CreateLabelActivity extends BaseActivity {
if(!connToInternet) { if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return; return;
} }
if(newLabelName.equals("")) { if(newLabelName.equals("")) {
Toasty.error(ctx, getString(R.string.labelEmptyError)); Toasty.info(getApplicationContext(), getString(R.string.labelEmptyError));
return; return;
} }
if(!appUtil.checkStrings(newLabelName)) { if(!appUtil.checkStrings(newLabelName)) {
Toasty.error(ctx, getString(R.string.labelNameError)); Toasty.info(getApplicationContext(), getString(R.string.labelNameError));
return; return;
} }
@ -236,14 +238,14 @@ public class CreateLabelActivity extends BaseActivity {
private void createNewLabel(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String newLabelName, String newLabelColor, String loginUid) { private void createNewLabel(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String newLabelName, String newLabelColor, String loginUid) {
CreateLabel createLabelFunc = new CreateLabel(newLabelName, newLabelColor); CreateLabel createLabelFunc = new CreateLabel(newLabelName, newLabelColor);
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<CreateLabel> call; Call<CreateLabel> call;
call = RetrofitClient call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.createLabel(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, createLabelFunc); .createLabel(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, createLabelFunc);
call.enqueue(new Callback<CreateLabel>() { call.enqueue(new Callback<CreateLabel>() {
@ -252,7 +254,7 @@ public class CreateLabelActivity extends BaseActivity {
if(response.code() == 201) { if(response.code() == 201) {
Toasty.success(ctx, getString(R.string.labelCreated)); Toasty.info(getApplicationContext(), getString(R.string.labelCreated));
tinyDb.putString("labelColor", ""); tinyDb.putString("labelColor", "");
tinyDb.putBoolean("labelsRefresh", true); tinyDb.putBoolean("labelsRefresh", true);
finish(); finish();
@ -271,7 +273,7 @@ public class CreateLabelActivity extends BaseActivity {
enableProcessButton(); enableProcessButton();
tinyDb.putString("labelColor", ""); tinyDb.putString("labelColor", "");
Toasty.error(ctx, getString(R.string.labelGeneralError)); Toasty.info(getApplicationContext(), getString(R.string.labelGeneralError));
} }
@ -279,7 +281,6 @@ public class CreateLabelActivity extends BaseActivity {
@Override @Override
public void onFailure(@NonNull Call<CreateLabel> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<CreateLabel> call, @NonNull Throwable t) {
tinyDb.putString("labelColor", ""); tinyDb.putString("labelColor", "");
Log.e("onFailure", t.toString()); Log.e("onFailure", t.toString());
enableProcessButton(); enableProcessButton();
@ -291,14 +292,14 @@ public class CreateLabelActivity extends BaseActivity {
private void patchLabel(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String updateLabelName, String updateLabelColor, int labelId, String loginUid) { private void patchLabel(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String updateLabelName, String updateLabelColor, int labelId, String loginUid) {
CreateLabel createLabelFunc = new CreateLabel(updateLabelName, updateLabelColor); CreateLabel createLabelFunc = new CreateLabel(updateLabelName, updateLabelColor);
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<CreateLabel> call; Call<CreateLabel> call;
call = RetrofitClient call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.patchLabel(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, labelId, createLabelFunc); .patchLabel(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, labelId, createLabelFunc);
call.enqueue(new Callback<CreateLabel>() { call.enqueue(new Callback<CreateLabel>() {
@ -308,7 +309,7 @@ public class CreateLabelActivity extends BaseActivity {
if(response.isSuccessful()) { if(response.isSuccessful()) {
if(response.code() == 200) { if(response.code() == 200) {
Toasty.success(ctx, getString(R.string.labelUpdated)); Toasty.info(getApplicationContext(), getString(R.string.labelUpdated));
tinyDb.putString("labelColor", ""); tinyDb.putString("labelColor", "");
tinyDb.putBoolean("labelsRefresh", true); tinyDb.putBoolean("labelsRefresh", true);
tinyDb.putString("labelColorDefault", ""); tinyDb.putString("labelColorDefault", "");
@ -334,7 +335,7 @@ public class CreateLabelActivity extends BaseActivity {
enableProcessButton(); enableProcessButton();
tinyDb.putString("labelColor", ""); tinyDb.putString("labelColor", "");
tinyDb.putString("labelColorDefault", ""); tinyDb.putString("labelColorDefault", "");
Toasty.error(ctx, getString(R.string.labelGeneralError)); Toasty.info(getApplicationContext(), getString(R.string.labelGeneralError));
} }
@ -342,7 +343,6 @@ public class CreateLabelActivity extends BaseActivity {
@Override @Override
public void onFailure(@NonNull Call<CreateLabel> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<CreateLabel> call, @NonNull Throwable t) {
tinyDb.putString("labelColor", ""); tinyDb.putString("labelColor", "");
tinyDb.putString("labelColorDefault", ""); tinyDb.putString("labelColorDefault", "");
Log.e("onFailure", t.toString()); Log.e("onFailure", t.toString());
@ -370,9 +370,9 @@ public class CreateLabelActivity extends BaseActivity {
Call<Labels> call; Call<Labels> call;
call = RetrofitClient call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.deleteLabel(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, labelId); .deleteLabel(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, labelId);
call.enqueue(new Callback<Labels>() { call.enqueue(new Callback<Labels>() {
@ -382,8 +382,8 @@ public class CreateLabelActivity extends BaseActivity {
if(response.isSuccessful()) { if(response.isSuccessful()) {
if(response.code() == 204) { if(response.code() == 204) {
Toasty.success(ctx, getString(R.string.labelDeleteText)); Toasty.info(getApplicationContext(), getString(R.string.labelDeleteText));
LabelsViewModel.loadLabelsList(instanceUrl, instanceToken, repoOwner, repoName, ctx); LabelsViewModel.loadLabelsList(instanceUrl, instanceToken, repoOwner, repoName, getApplicationContext());
getIntent().removeExtra("labelAction"); getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId"); getIntent().removeExtra("labelId");
@ -399,7 +399,7 @@ public class CreateLabelActivity extends BaseActivity {
} }
else { else {
Toasty.error(ctx, getString(R.string.labelDeleteErrorText)); Toasty.info(getApplicationContext(), getString(R.string.labelDeleteErrorText));
} }
@ -416,11 +416,21 @@ public class CreateLabelActivity extends BaseActivity {
private void disableProcessButton() { private void disableProcessButton() {
createLabelButton.setEnabled(false); createLabelButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createLabelButton.setBackground(shape);
} }
private void enableProcessButton() { private void enableProcessButton() {
createLabelButton.setEnabled(true); createLabelButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createLabelButton.setBackground(shape);
} }
} }

View File

@ -1,31 +1,32 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.util.Patterns; import android.util.Patterns;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserInfo; import org.mian.gitnex.models.UserInfo;
import retrofit2.Call; import org.mian.gitnex.util.AppUtil;
import retrofit2.Callback; import org.mian.gitnex.util.TinyDB;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class CreateNewUserActivity extends BaseActivity { public class CreateNewUserActivity extends AppCompatActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private EditText fullName; private EditText fullName;
@ -34,22 +35,14 @@ public class CreateNewUserActivity extends BaseActivity {
private EditText userPassword; private EditText userPassword;
private Button createUserButton; private Button createUserButton;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_create_new_user;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_create_new_user);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = findViewById(R.id.close);
createUserButton = findViewById(R.id.createUserButton); createUserButton = findViewById(R.id.createUserButton);
@ -58,29 +51,26 @@ public class CreateNewUserActivity extends BaseActivity {
userEmail = findViewById(R.id.userEmail); userEmail = findViewById(R.id.userEmail);
userPassword = findViewById(R.id.userPassword); userPassword = findViewById(R.id.userPassword);
fullName.requestFocus();
assert imm != null;
imm.showSoftInput(fullName, InputMethodManager.SHOW_IMPLICIT);
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
if(!connToInternet) { if(!connToInternet) {
disableProcessButton(); disableProcessButton();
}
else { } else {
createUserButton.setOnClickListener(createNewUserListener); createUserButton.setOnClickListener(createNewUserListener);
} }
} }
private void processCreateNewUser() { private void processCreateNewUser() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
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");
@ -92,41 +82,41 @@ public class CreateNewUserActivity extends BaseActivity {
if(!connToInternet) { if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return; return;
} }
if(newFullName.equals("") || newUserName.equals("") | newUserEmail.equals("") || newUserPassword.equals("")) { if(newFullName.equals("") || newUserName.equals("") | newUserEmail.equals("") || newUserPassword.equals("")) {
Toasty.error(ctx, getString(R.string.emptyFields)); Toasty.info(getApplicationContext(), getString(R.string.emptyFields));
return; return;
} }
if(!appUtil.checkStrings(newFullName)) { if(!appUtil.checkStrings(newFullName)) {
Toasty.error(ctx, getString(R.string.userInvalidFullName)); Toasty.info(getApplicationContext(), getString(R.string.userInvalidFullName));
return; return;
} }
if(!appUtil.checkStringsWithAlphaNumeric(newUserName)) { if(!appUtil.checkStringsWithAlphaNumeric(newUserName)) {
Toasty.error(ctx, getString(R.string.userInvalidUserName)); Toasty.info(getApplicationContext(), getString(R.string.userInvalidUserName));
return; return;
} }
if(!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) { if(!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) {
Toasty.error(ctx, getString(R.string.userInvalidEmail)); Toasty.info(getApplicationContext(), getString(R.string.userInvalidEmail));
return; return;
} }
disableProcessButton(); disableProcessButton();
createNewUser(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), newFullName, newUserName, newUserEmail, newUserPassword); createNewUser(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), newFullName, newUserName, newUserEmail, newUserPassword);
} }
@ -137,7 +127,7 @@ public class CreateNewUserActivity extends BaseActivity {
Call<UserInfo> call; Call<UserInfo> call;
call = RetrofitClient call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.createNewUser(instanceToken, createUser); .createNewUser(instanceToken, createUser);
@ -148,7 +138,7 @@ public class CreateNewUserActivity extends BaseActivity {
if(response.code() == 201) { if(response.code() == 201) {
Toasty.success(ctx, getString(R.string.userCreatedText)); Toasty.info(getApplicationContext(), getString(R.string.userCreatedText));
enableProcessButton(); enableProcessButton();
finish(); finish();
@ -165,25 +155,25 @@ public class CreateNewUserActivity extends BaseActivity {
else if(response.code() == 403) { else if(response.code() == 403) {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); Toasty.info(ctx, ctx.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
enableProcessButton(); enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)); Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
} }
else if(response.code() == 422) { else if(response.code() == 422) {
enableProcessButton(); enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.userExistsError)); Toasty.info(ctx, ctx.getString(R.string.userExistsError));
} }
else { else {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError)); Toasty.info(getApplicationContext(), getString(R.string.genericError));
} }
@ -191,7 +181,6 @@ public class CreateNewUserActivity extends BaseActivity {
@Override @Override
public void onFailure(@NonNull Call<UserInfo> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<UserInfo> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString()); Log.e("onFailure", t.toString());
enableProcessButton(); enableProcessButton();
} }
@ -199,21 +188,39 @@ public class CreateNewUserActivity extends BaseActivity {
} }
private View.OnClickListener createNewUserListener = v -> processCreateNewUser(); private View.OnClickListener createNewUserListener = new View.OnClickListener() {
public void onClick(View v) {
processCreateNewUser();
}
};
private void initCloseListener() { private void initCloseListener() {
onClickListener = new View.OnClickListener() {
onClickListener = view -> finish(); @Override
public void onClick(View view) {
finish();
}
};
} }
private void disableProcessButton() { private void disableProcessButton() {
createUserButton.setEnabled(false); createUserButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createUserButton.setBackground(shape);
} }
private void enableProcessButton() { private void enableProcessButton() {
createUserButton.setEnabled(true); createUserButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createUserButton.setBackground(shape);
} }
} }

View File

@ -1,10 +1,15 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context; import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
@ -12,26 +17,23 @@ import android.widget.CheckBox;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Spinner; import android.widget.Spinner;
import androidx.annotation.NonNull;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Branches; import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.Releases; import org.mian.gitnex.models.Releases;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class CreateReleaseActivity extends BaseActivity { public class CreateReleaseActivity extends AppCompatActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
public ImageView closeActivity; public ImageView closeActivity;
@ -43,26 +45,18 @@ public class CreateReleaseActivity extends BaseActivity {
private CheckBox releaseDraft; private CheckBox releaseDraft;
private Button createNewRelease; private Button createNewRelease;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
List<Branches> branchesList = new ArrayList<>(); List<Branches> branchesList = new ArrayList<>();
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_create_release;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_create_release);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); TinyDB tinyDb = new TinyDB(getApplicationContext());
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");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
@ -78,15 +72,12 @@ public class CreateReleaseActivity extends BaseActivity {
releaseType = findViewById(R.id.releaseType); releaseType = findViewById(R.id.releaseType);
releaseDraft = findViewById(R.id.releaseDraft); releaseDraft = findViewById(R.id.releaseDraft);
releaseTagName.requestFocus();
assert imm != null;
imm.showSoftInput(releaseTagName, InputMethodManager.SHOW_IMPLICIT);
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
releaseBranch = findViewById(R.id.releaseBranch); releaseBranch = findViewById(R.id.releaseBranch);
getBranches(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName); releaseBranch.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
getBranches(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
releaseBranch.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { releaseBranch.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
@ -105,21 +96,26 @@ public class CreateReleaseActivity extends BaseActivity {
if(!connToInternet) { if(!connToInternet) {
disableProcessButton(); disableProcessButton();
}
else { } else {
createNewRelease.setOnClickListener(createReleaseListener); createNewRelease.setOnClickListener(createReleaseListener);
} }
} }
private View.OnClickListener createReleaseListener = v -> processNewRelease(); private View.OnClickListener createReleaseListener = new View.OnClickListener() {
public void onClick(View v) {
processNewRelease();
}
};
private void processNewRelease() { private void processNewRelease() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
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");
@ -137,27 +133,27 @@ public class CreateReleaseActivity extends BaseActivity {
if(!connToInternet) { if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return; return;
} }
if(newReleaseTagName.equals("")) { if(newReleaseTagName.equals("")) {
Toasty.error(ctx, getString(R.string.tagNameErrorEmpty)); Toasty.info(getApplicationContext(), getString(R.string.tagNameErrorEmpty));
return; return;
} }
if(newReleaseTitle.equals("")) { if(newReleaseTitle.equals("")) {
Toasty.error(ctx, getString(R.string.titleErrorEmpty)); Toasty.info(getApplicationContext(), getString(R.string.titleErrorEmpty));
return; return;
} }
disableProcessButton(); disableProcessButton();
createNewReleaseFunc(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, newReleaseTagName, newReleaseTitle, newReleaseContent, newReleaseBranch, newReleaseType, newReleaseDraft); createNewReleaseFunc(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, newReleaseTagName, newReleaseTitle, newReleaseContent, newReleaseBranch, newReleaseType, newReleaseDraft);
} }
@ -168,7 +164,7 @@ public class CreateReleaseActivity extends BaseActivity {
Call<Releases> call; Call<Releases> call;
call = RetrofitClient call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.createNewRelease(token, repoOwner, repoName, createReleaseJson); .createNewRelease(token, repoOwner, repoName, createReleaseJson);
@ -179,9 +175,9 @@ public class CreateReleaseActivity extends BaseActivity {
if (response.code() == 201) { if (response.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("updateReleases", true); tinyDb.putBoolean("updateReleases", true);
Toasty.success(ctx, getString(R.string.releaseCreatedText)); Toasty.info(getApplicationContext(), getString(R.string.releaseCreatedText));
enableProcessButton(); enableProcessButton();
finish(); finish();
@ -198,19 +194,19 @@ public class CreateReleaseActivity extends BaseActivity {
else if(response.code() == 403) { else if(response.code() == 403) {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); Toasty.info(ctx, ctx.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
enableProcessButton(); enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)); Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
} }
else { else {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.genericError)); Toasty.info(ctx, ctx.getString(R.string.genericError));
} }
@ -228,7 +224,7 @@ public class CreateReleaseActivity extends BaseActivity {
private void getBranches(String instanceUrl, String instanceToken, final String repoOwner, final String repoName) { private void getBranches(String instanceUrl, String instanceToken, final String repoOwner, final String repoName) {
Call<List<Branches>> call = RetrofitClient Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getBranches(instanceToken, repoOwner, repoName); .getBranches(instanceToken, repoOwner, repoName);
@ -254,7 +250,7 @@ public class CreateReleaseActivity extends BaseActivity {
} }
} }
ArrayAdapter<Branches> adapter = new ArrayAdapter<>(CreateReleaseActivity.this, ArrayAdapter<Branches> adapter = new ArrayAdapter<>(getApplicationContext(),
R.layout.spinner_item, branchesList); R.layout.spinner_item, branchesList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item); adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
@ -294,11 +290,21 @@ public class CreateReleaseActivity extends BaseActivity {
private void disableProcessButton() { private void disableProcessButton() {
createNewRelease.setEnabled(false); createNewRelease.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewRelease.setBackground(shape);
} }
private void enableProcessButton() { private void enableProcessButton() {
createNewRelease.setEnabled(true); createNewRelease.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createNewRelease.setBackground(shape);
} }
} }

View File

@ -1,38 +1,38 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Teams; import org.mian.gitnex.models.Teams;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import retrofit2.Call; import android.util.Log;
import retrofit2.Callback;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClickListener { public class CreateTeamByOrgActivity extends AppCompatActivity implements View.OnClickListener {
final Context ctx = CreateTeamByOrgActivity.this; final Context ctx = CreateTeamByOrgActivity.this;
private Context appCtx;
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private TextView teamName; private TextView teamName;
private TextView teamDesc; private TextView teamDesc;
@ -44,11 +44,6 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
private String[] permissionList = {"Read", "Write", "Admin"}; private String[] permissionList = {"Read", "Write", "Admin"};
public int permissionSelectedChoice = -1; public int permissionSelectedChoice = -1;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_create_team_by_org;
}
private String[] accessControlsList = new String[] { private String[] accessControlsList = new String[] {
"Code", "Code",
"Issues", "Issues",
@ -72,14 +67,11 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
}; };
@Override @Override
public void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_create_team_by_org);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = findViewById(R.id.close);
teamName = findViewById(R.id.teamName); teamName = findViewById(R.id.teamName);
@ -90,127 +82,137 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
teamAccessControlsArray = findViewById(R.id.teamAccessControlsArray); teamAccessControlsArray = findViewById(R.id.teamAccessControlsArray);
createTeamButton = findViewById(R.id.createTeamButton); createTeamButton = findViewById(R.id.createTeamButton);
teamName.requestFocus();
assert imm != null;
imm.showSoftInput(teamName, InputMethodManager.SHOW_IMPLICIT);
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
teamPermission.setOnClickListener(view -> { teamPermission.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx); AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx, R.style.confirmDialog);
pBuilder.setTitle(R.string.newTeamPermission);
if(permissionSelectedChoice != -1) {
pBuilder.setCancelable(true);
}
else {
pBuilder.setCancelable(false);
}
pBuilder.setSingleChoiceItems(permissionList, permissionSelectedChoice, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
permissionSelectedChoice = i;
teamPermission.setText(permissionList[i]);
if(permissionList[i].equals("Read")) {
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionRead);
}
else if(permissionList[i].equals("Write")) {
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionWrite);
}
else if(permissionList[i].equals("Admin")) {
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionAdmin);
}
else {
teamPermissionDetail.setVisibility(View.GONE);
}
dialogInterface.dismiss();
}
});
AlertDialog pDialog = pBuilder.create();
pDialog.show();
pBuilder.setTitle(R.string.newTeamPermission);
if(permissionSelectedChoice != -1) {
pBuilder.setCancelable(true);
} }
else {
pBuilder.setCancelable(false);
}
pBuilder.setSingleChoiceItems(permissionList, permissionSelectedChoice, (dialogInterface, i) -> {
permissionSelectedChoice = i;
teamPermission.setText(permissionList[i]);
switch(permissionList[i]) {
case "Read":
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionRead);
break;
case "Write":
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionWrite);
break;
case "Admin":
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionAdmin);
break;
default:
teamPermissionDetail.setVisibility(View.GONE);
break;
}
dialogInterface.dismiss();
});
AlertDialog pDialog = pBuilder.create();
pDialog.show();
}); });
teamAccessControls.setOnClickListener(v -> { teamAccessControls.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
teamAccessControls.setText(""); teamAccessControls.setText("");
teamAccessControlsArray.setText(""); teamAccessControlsArray.setText("");
pushAccessList = Arrays.asList(accessControlsList); pushAccessList = Arrays.asList(accessControlsList);
AlertDialog.Builder aDialogBuilder = new AlertDialog.Builder(ctx); AlertDialog.Builder aDialogBuilder = new AlertDialog.Builder(ctx, R.style.confirmDialog);
aDialogBuilder.setMultiChoiceItems(accessControlsList, selectedAccessControlsTrueFalse, (dialog, which, isChecked) -> { aDialogBuilder.setMultiChoiceItems(accessControlsList, selectedAccessControlsTrueFalse, new DialogInterface.OnMultiChoiceClickListener() {
}) @Override
.setCancelable(false) public void onClick(DialogInterface dialog, int which, boolean isChecked) {
.setTitle(R.string.newTeamAccessControls)
.setPositiveButton(R.string.okButton, (dialog, which) -> {
int selectedVal = 0;
while(selectedVal < selectedAccessControlsTrueFalse.length)
{
boolean value = selectedAccessControlsTrueFalse[selectedVal];
String repoCode = "";
if(selectedVal == 0) {
repoCode = "repo.code";
}
if(selectedVal == 1) {
repoCode = "repo.issues";
}
if(selectedVal == 2) {
repoCode = "repo.pulls";
}
if(selectedVal == 3) {
repoCode = "repo.releases";
}
if(selectedVal == 4) {
repoCode = "repo.wiki";
}
if(selectedVal == 5) {
repoCode = "repo.ext_wiki";
}
if(selectedVal == 6) {
repoCode = "repo.ext_issues";
} }
if(value){ })
teamAccessControls.setText(getString(R.string.newTeamPermissionValues, teamAccessControls.getText(), pushAccessList.get(selectedVal))); .setCancelable(false)
teamAccessControlsArray.setText(getString(R.string.newTeamPermissionValuesFinal, teamAccessControlsArray.getText(), repoCode)); .setTitle(R.string.newTeamAccessControls)
.setPositiveButton(R.string.okButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int selectedVal = 0;
while(selectedVal < selectedAccessControlsTrueFalse.length)
{
boolean value = selectedAccessControlsTrueFalse[selectedVal];
String repoCode = "";
if(selectedVal == 0) {
repoCode = "repo.code";
}
if(selectedVal == 1) {
repoCode = "repo.issues";
}
if(selectedVal == 2) {
repoCode = "repo.pulls";
}
if(selectedVal == 3) {
repoCode = "repo.releases";
}
if(selectedVal == 4) {
repoCode = "repo.wiki";
}
if(selectedVal == 5) {
repoCode = "repo.ext_wiki";
}
if(selectedVal == 6) {
repoCode = "repo.ext_issues";
}
if(value){
teamAccessControls.setText(getString(R.string.newTeamPermissionValues, teamAccessControls.getText(), pushAccessList.get(selectedVal)));
teamAccessControlsArray.setText(getString(R.string.newTeamPermissionValuesFinal, teamAccessControlsArray.getText(), repoCode));
}
selectedVal++;
}
String data = String.valueOf(teamAccessControls.getText());
if(!data.equals("")) {
teamAccessControls.setText(data.substring(0, data.length() - 2));
}
String dataArray = String.valueOf(teamAccessControlsArray.getText());
if(!dataArray.equals("")) {
teamAccessControlsArray.setText(dataArray.substring(0, dataArray.length() - 2));
}
//Log.i("orgName", String.valueOf(teamAccessControlsArray.getText()));
} }
selectedVal++;
}
String data = String.valueOf(teamAccessControls.getText()); });
if(!data.equals("")) {
teamAccessControls.setText(data.substring(0, data.length() - 2));
}
String dataArray = String.valueOf(teamAccessControlsArray.getText()); AlertDialog aDialog = aDialogBuilder.create();
if(!dataArray.equals("")) { aDialog.show();
teamAccessControlsArray.setText(dataArray.substring(0, dataArray.length() - 2)); }
}
//Log.i("orgName", String.valueOf(teamAccessControlsArray.getText()));
});
AlertDialog aDialog = aDialogBuilder.create();
aDialog.show();
}); });
createTeamButton.setEnabled(false); createTeamButton.setEnabled(false);
@ -235,13 +237,13 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
private void processCreateTeam() { private void processCreateTeam() {
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(getApplicationContext());
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 orgName = tinyDb.getString("orgName");; final String orgName = tinyDb.getString("orgName");;
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
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();
@ -249,21 +251,21 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
if(!connToInternet) { if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return; return;
} }
if (newTeamName.equals("")) { if (newTeamName.equals("")) {
Toasty.error(ctx, getString(R.string.teamNameEmpty)); Toasty.info(getApplicationContext(), getString(R.string.teamNameEmpty));
return; return;
} }
if(!appUtil.checkStringsWithAlphaNumericDashDotUnderscore(newTeamName)) { if(!appUtil.checkStringsWithAlphaNumericDashDotUnderscore(newTeamName)) {
Toasty.warning(ctx, getString(R.string.teamNameError)); Toasty.info(getApplicationContext(), getString(R.string.teamNameError));
return; return;
} }
@ -271,12 +273,12 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
if(!newTeamDesc.equals("")) { if(!newTeamDesc.equals("")) {
if(!appUtil.checkStrings(newTeamDesc)) { if(!appUtil.checkStrings(newTeamDesc)) {
Toasty.warning(ctx, getString(R.string.teamDescError)); Toasty.info(getApplicationContext(), getString(R.string.teamDescError));
return; return;
} }
if(newTeamDesc.length() > 100) { if(newTeamDesc.length() > 100) {
Toasty.warning(ctx, getString(R.string.teamDescLimit)); Toasty.info(getApplicationContext(), getString(R.string.teamDescLimit));
return; return;
} }
@ -284,7 +286,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
if (newTeamPermission.equals("")) { if (newTeamPermission.equals("")) {
Toasty.error(ctx, getString(R.string.teamPermissionEmpty)); Toasty.info(getApplicationContext(), getString(R.string.teamPermissionEmpty));
return; return;
} }
@ -306,9 +308,9 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
Call<Teams> call3; Call<Teams> call3;
call3 = RetrofitClient call3 = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.createTeamsByOrg(Authorization.returnAuthentication(ctx, loginUid, instanceToken), orgName, createNewTeamJson); .createTeamsByOrg(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), orgName, createNewTeamJson);
call3.enqueue(new Callback<Teams>() { call3.enqueue(new Callback<Teams>() {
@ -318,17 +320,19 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
if(response2.isSuccessful()) { if(response2.isSuccessful()) {
if(response2.code() == 201) { if(response2.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("resumeTeams", true); tinyDb.putBoolean("resumeTeams", true);
Toasty.success(ctx, getString(R.string.teamCreated)); Toasty.info(getApplicationContext(), getString(R.string.teamCreated));
finish(); finish();
} }
} }
else if(response2.code() == 404) { else if(response2.code() == 404) {
Toasty.warning(ctx, getString(R.string.apiNotFound)); Toasty.info(getApplicationContext(), getString(R.string.apiNotFound));
} }
else if(response2.code() == 401) { else if(response2.code() == 401) {
@ -336,10 +340,12 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
} }
else { else {
Toasty.error(ctx, getString(R.string.teamCreatedError)); Toasty.info(getApplicationContext(), getString(R.string.teamCreatedError));
} }
} }
@ -354,15 +360,19 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if(v == createTeamButton) { if(v == createTeamButton) {
processCreateTeam(); processCreateTeam();
} }
} }
private void initCloseListener() { private void initCloseListener() {
onClickListener = new View.OnClickListener() {
onClickListener = view -> finish(); @Override
public void onClick(View view) {
finish();
}
};
} }
} }

View File

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

View File

@ -1,12 +1,18 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.DatePickerDialog; import android.app.DatePickerDialog;
import android.content.Context; import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.DatePicker; import android.widget.DatePicker;
@ -14,7 +20,6 @@ import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.hendraanggrian.appcompat.socialview.Mention; import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter; import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
@ -22,35 +27,28 @@ import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Collaborators; import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.CreateIssue; import org.mian.gitnex.models.CreateIssue;
import org.mian.gitnex.models.Issues; import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.Milestones; import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class EditIssueActivity extends BaseActivity implements View.OnClickListener { public class EditIssueActivity extends AppCompatActivity implements View.OnClickListener {
final Context ctx = this; final Context ctx = this;
private Context appCtx;
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private EditText editIssueTitle; private EditText editIssueTitle;
private SocialAutoCompleteTextView editIssueDescription; private SocialAutoCompleteTextView editIssueDescription;
@ -64,19 +62,12 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
private ArrayAdapter<Mention> defaultMentionAdapter; private ArrayAdapter<Mention> defaultMentionAdapter;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_edit_issue;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_edit_issue);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); final TinyDB tinyDb = new TinyDB(getApplicationContext());
final 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");
@ -94,19 +85,11 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
editIssueDescription = findViewById(R.id.editIssueDescription); editIssueDescription = findViewById(R.id.editIssueDescription);
editIssueDueDate = findViewById(R.id.editIssueDueDate); editIssueDueDate = findViewById(R.id.editIssueDueDate);
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
}
editIssueTitle.requestFocus();
assert imm != null;
imm.showSoftInput(editIssueTitle, InputMethodManager.SHOW_IMPLICIT);
defaultMentionAdapter = new MentionArrayAdapter<>(this); defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList(); loadCollaboratorsList();
editIssueMilestoneSpinner = findViewById(R.id.editIssueMilestoneSpinner); editIssueMilestoneSpinner = findViewById(R.id.editIssueMilestoneSpinner);
editIssueMilestoneSpinner.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
editIssueDescription.setMentionAdapter(defaultMentionAdapter); editIssueDescription.setMentionAdapter(defaultMentionAdapter);
@ -118,7 +101,7 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
if(!tinyDb.getString("issueNumber").isEmpty()) { if(!tinyDb.getString("issueNumber").isEmpty()) {
if(tinyDb.getString("issueType").equalsIgnoreCase("Pull")) { if(tinyDb.getString("issueType").equals("pr")) {
toolbar_title.setText(getString(R.string.editPrNavHeader, String.valueOf(issueIndex))); toolbar_title.setText(getString(R.string.editPrNavHeader, String.valueOf(issueIndex)));
} }
else { else {
@ -127,14 +110,14 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
} }
disableProcessButton(); disableProcessButton();
getIssue(instanceUrl, instanceToken, loginUid, repoOwner, repoName, issueIndex, resultLimit); getIssue(instanceUrl, instanceToken, loginUid, repoOwner, repoName, issueIndex);
} }
public void loadCollaboratorsList() { public void loadCollaboratorsList() {
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid"); final String loginUid = tinyDb.getString("loginUid");
@ -145,9 +128,9 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
final String repoName = parts[1]; final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName); .getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() { call.enqueue(new Callback<List<Collaborators>>() {
@ -193,8 +176,8 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
private void processEditIssue() { private void processEditIssue() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl"); final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid"); final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName"); String repoFullName = tinyDb.getString("repoFullName");
@ -214,21 +197,21 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
if(!connToInternet) { if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return; return;
} }
if (editIssueTitleForm.equals("")) { if (editIssueTitleForm.equals("")) {
Toasty.error(ctx, getString(R.string.issueTitleEmpty)); Toasty.info(getApplicationContext(), getString(R.string.issueTitleEmpty));
return; return;
} }
/*if (editIssueDescriptionForm.equals("")) { /*if (editIssueDescriptionForm.equals("")) {
Toasty.info(ctx, getString(R.string.issueDescriptionEmpty)); Toasty.info(getApplicationContext(), getString(R.string.issueDescriptionEmpty));
return; return;
}*/ }*/
@ -247,14 +230,14 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
private void editIssue(String instanceUrl, String instanceToken, String repoOwner, String repoName, int issueIndex, String loginUid, String title, String description, String dueDate, int editIssueMilestoneId) { private void editIssue(String instanceUrl, String instanceToken, String repoOwner, String repoName, int issueIndex, String loginUid, String title, String description, String dueDate, int editIssueMilestoneId) {
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(getApplicationContext());
CreateIssue issueData = new CreateIssue(title, description, dueDate, editIssueMilestoneId); CreateIssue issueData = new CreateIssue(title, description, dueDate, editIssueMilestoneId);
Call<JsonElement> call = RetrofitClient Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.patchIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueData); .patchIssue(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, issueData);
call.enqueue(new Callback<JsonElement>() { call.enqueue(new Callback<JsonElement>() {
@ -263,11 +246,11 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
if(response.code() == 201) { if(response.code() == 201) {
if(tinyDb.getString("issueType").equalsIgnoreCase("Pull")) { if(tinyDb.getString("issueType").equals("pr")) {
Toasty.success(ctx, getString(R.string.editPrSuccessMessage)); Toasty.info(getApplicationContext(), getString(R.string.editPrSuccessMessage));
} }
else { else {
Toasty.success(ctx, getString(R.string.editIssueSuccessMessage)); Toasty.info(getApplicationContext(), getString(R.string.editIssueSuccessMessage));
} }
tinyDb.putBoolean("issueEdited", true); tinyDb.putBoolean("issueEdited", true);
@ -287,7 +270,7 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
else { else {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError)); Toasty.info(getApplicationContext(), getString(R.string.genericError));
} }
@ -333,12 +316,12 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
} }
private void getIssue(final String instanceUrl, final String instanceToken, final String loginUid, final String repoOwner, final String repoName, int issueIndex, int resultLimit) { private void getIssue(final String instanceUrl, final String instanceToken, final String loginUid, final String repoOwner, final String repoName, int issueIndex) {
Call<Issues> call = RetrofitClient Call<Issues> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex); .getIssueByIndex(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
call.enqueue(new Callback<Issues>() { call.enqueue(new Callback<Issues>() {
@ -360,9 +343,9 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
if(response.body().getId() > 0) { if(response.body().getId() > 0) {
Call<List<Milestones>> call_ = RetrofitClient Call<List<Milestones>> call_ = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getMilestones(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, 1, resultLimit, msState); .getMilestones(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, msState);
final int finalMsId = msId; final int finalMsId = msId;
@ -395,7 +378,7 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
} }
} }
ArrayAdapter<Milestones> adapter_ = new ArrayAdapter<>(EditIssueActivity.this, ArrayAdapter<Milestones> adapter_ = new ArrayAdapter<>(getApplicationContext(),
R.layout.spinner_item, milestonesList); R.layout.spinner_item, milestonesList);
adapter_.setDropDownViewResource(R.layout.spinner_dropdown_item); adapter_.setDropDownViewResource(R.layout.spinner_dropdown_item);
@ -424,6 +407,7 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
@SuppressLint("SimpleDateFormat") DateFormat formatter = new SimpleDateFormat("yyyy-M-dd"); @SuppressLint("SimpleDateFormat") DateFormat formatter = new SimpleDateFormat("yyyy-M-dd");
String dueDate = formatter.format(response.body().getDue_date()); String dueDate = formatter.format(response.body().getDue_date());
editIssueDueDate.setText(dueDate); editIssueDueDate.setText(dueDate);
} }
//enableProcessButton(); //enableProcessButton();
@ -434,10 +418,12 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
} }
else { else {
Toasty.error(ctx, getString(R.string.genericError)); Toasty.info(getApplicationContext(), getString(R.string.genericError));
} }
} }
@ -453,11 +439,21 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
private void disableProcessButton() { private void disableProcessButton() {
editIssueButton.setEnabled(false); editIssueButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
editIssueButton.setBackground(shape);
} }
private void enableProcessButton() { private void enableProcessButton() {
editIssueButton.setEnabled(true); editIssueButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
editIssueButton.setBackground(shape);
} }
} }

View File

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

View File

@ -1,66 +1,33 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.Spanned;
import android.text.method.ScrollingMovementMethod; import android.text.method.ScrollingMovementMethod;
import android.util.Base64; import android.util.Base64;
import android.util.Log; import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
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.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.util.FitPolicy;
import com.github.chrisbanes.photoview.PhotoView; import com.github.chrisbanes.photoview.PhotoView;
import org.apache.commons.io.FileUtils; import com.pddstudio.highlightjs.HighlightJsView;
import com.pddstudio.highlightjs.models.Theme;
import org.apache.commons.io.FilenameUtils;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BottomSheetFileViewerFragment;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.highlightjs.HighlightJsView;
import org.mian.gitnex.helpers.highlightjs.models.Theme;
import org.mian.gitnex.models.Files; import org.mian.gitnex.models.Files;
import java.io.File; import org.mian.gitnex.util.AppUtil;
import java.io.IOException; import org.mian.gitnex.util.TinyDB;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin;
import io.noties.markwon.core.MarkwonTheme;
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tasklist.TaskListPlugin;
import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.DefaultMediaDecoder;
import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin;
import io.noties.markwon.image.SchemeHandler;
import io.noties.markwon.image.gif.GifMediaDecoder;
import io.noties.markwon.image.svg.SvgMediaDecoder;
import io.noties.markwon.linkify.LinkifyPlugin;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -68,469 +35,171 @@ import retrofit2.Callback;
* Author M M Arif * Author M M Arif
*/ */
public class FileViewActivity extends BaseActivity implements BottomSheetFileViewerFragment.BottomSheetListener { public class FileViewActivity extends AppCompatActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private TextView singleFileContents; private TextView singleFileContents;
private LinearLayout singleFileContentsFrame; private HighlightJsView singleCodeContents;
private HighlightJsView singleCodeContents; private PhotoView imageView;
private PhotoView imageView; final Context ctx = this;
final Context ctx = this; private ProgressBar mProgressBar;
private Context appCtx; private byte[] imageData;
private ProgressBar mProgressBar;
private byte[] imageData;
private PDFView pdfView;
private LinearLayout pdfViewFrame;
private byte[] decodedPdf;
private Boolean pdfNightMode;
private String singleFileName;
private String fileSha;
private AppUtil appUtil;
private TinyDB tinyDb;
@Override @Override
protected int getLayoutResourceId() { protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_file_view; super.onCreate(savedInstanceState);
} setContentView(R.layout.activity_file_view);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@Override final TinyDB tinyDb = new TinyDB(getApplicationContext());
public void onCreate(Bundle savedInstanceState) { String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
super.onCreate(savedInstanceState); ImageView closeActivity = findViewById(R.id.close);
appCtx = getApplicationContext(); singleFileContents = findViewById(R.id.singleFileContents);
appUtil = new AppUtil(); singleCodeContents = findViewById(R.id.singleCodeContents);
tinyDb = new TinyDB(appCtx); imageView = findViewById(R.id.imageView);
singleFileContents.setVisibility(View.GONE);
mProgressBar = findViewById(R.id.progress_bar);
Toolbar toolbar = findViewById(R.id.toolbar); String singleFileName = getIntent().getStringExtra("singleFileName");
setSupportActionBar(toolbar);
String repoFullName = tinyDb.getString("repoFullName"); TextView toolbar_title = findViewById(R.id.toolbar_title);
String repoBranch = tinyDb.getString("repoBranch"); toolbar_title.setMovementMethod(new ScrollingMovementMethod());
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");
tinyDb.putBoolean("enableMarkdownInFileView", false); initCloseListener();
closeActivity.setOnClickListener(onClickListener);
ImageView closeActivity = findViewById(R.id.close); try {
singleFileContents = findViewById(R.id.singleFileContents);
singleCodeContents = findViewById(R.id.singleCodeContents);
imageView = findViewById(R.id.imageView);
mProgressBar = findViewById(R.id.progress_bar);
pdfView = findViewById(R.id.pdfView);
pdfViewFrame = findViewById(R.id.pdfViewFrame);
singleFileContentsFrame = findViewById(R.id.singleFileContentsFrame);
singleFileName = getIntent().getStringExtra("singleFileName"); singleFileName = URLDecoder.decode(singleFileName, "UTF-8");
singleFileName = singleFileName.replaceAll("//", "/");
singleFileName = singleFileName.startsWith("/") ? singleFileName.substring(1) : singleFileName;
TextView toolbar_title = findViewById(R.id.toolbar_title); }
toolbar_title.setMovementMethod(new ScrollingMovementMethod()); catch (UnsupportedEncodingException e) {
initCloseListener(); assert singleFileName != null;
closeActivity.setOnClickListener(onClickListener); Log.i("singleFileName", singleFileName);
tinyDb.putString("downloadFileContents", ""); }
try { toolbar_title.setText(singleFileName);
singleFileName = URLDecoder.decode(singleFileName, "UTF-8"); getSingleFileContents(instanceUrl, instanceToken, repoOwner, repoName, singleFileName);
singleFileName = singleFileName.replaceAll("//", "/");
singleFileName = singleFileName.startsWith("/") ? singleFileName.substring(1) : singleFileName;
} }
catch(UnsupportedEncodingException e) {
Log.i("singleFileName", singleFileName); private void getSingleFileContents(String instanceUrl, String token, final String owner, String repo, final String filename) {
} Call<Files> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getSingleFileContents(token, owner, repo, filename);
toolbar_title.setText(singleFileName); call.enqueue(new Callback<Files>() {
getSingleFileContents(instanceUrl, instanceToken, repoOwner, repoName, singleFileName, repoBranch); @Override
public void onResponse(@NonNull Call<Files> call, @NonNull retrofit2.Response<Files> response) {
} if (response.code() == 200) {
@Override AppUtil appUtil = new AppUtil();
public void onResume() { assert response.body() != null;
super.onResume(); if(!response.body().getContent().equals("")) {
String repoFullName = tinyDb.getString("repoFullName"); String fileExtension = FilenameUtils.getExtension(filename);
String repoBranch = tinyDb.getString("repoBranch"); mProgressBar.setVisibility(View.GONE);
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
String instanceUrl = tinyDb.getString("instanceUrl");
String loginUid = tinyDb.getString("loginUid");
String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getBoolean("fileModified")) { if(appUtil.imageExtension(fileExtension)) { // file is image
getSingleFileContents(instanceUrl, instanceToken, repoOwner, repoName, singleFileName, repoBranch);
tinyDb.putBoolean("fileModified", false);
}
}
singleFileContents.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
private void getSingleFileContents(String instanceUrl, String token, final String owner, String repo, final String filename, String ref) { imageData = Base64.decode(response.body().getContent(), Base64.DEFAULT);
Drawable imageDrawable = new BitmapDrawable(getResources(), BitmapFactory.decodeByteArray(imageData, 0, imageData.length));
imageView.setImageDrawable(imageDrawable);
Call<Files> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getSingleFileContents(token, owner, repo, filename, ref); }
else if (appUtil.sourceCodeExtension(fileExtension)) { // file is sourcecode
call.enqueue(new Callback<Files>() { imageView.setVisibility(View.GONE);
singleFileContents.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.VISIBLE);
@Override singleCodeContents.setTheme(Theme.GRUVBOX_DARK);
public void onResponse(@NonNull Call<Files> call, @NonNull retrofit2.Response<Files> response) { singleCodeContents.setShowLineNumbers(true);
singleCodeContents.setSource(appUtil.decodeBase64(response.body().getContent()));
if(response.code() == 200) { }
else { // file type not known - plain text view
assert response.body() != null; imageView.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
singleFileContents.setVisibility(View.VISIBLE);
if(!response.body().getContent().equals("")) { singleFileContents.setText(appUtil.decodeBase64(response.body().getContent()));
String fileExtension = FileUtils.getExtension(filename); }
mProgressBar.setVisibility(View.GONE);
fileSha = response.body().getSha(); }
else {
singleFileContents.setText("");
mProgressBar.setVisibility(View.GONE);
}
// download file meta }
tinyDb.putString("downloadFileName", filename); else if(response.code() == 401) {
tinyDb.putString("downloadFileContents", response.body().getContent());
if(appUtil.imageExtension(fileExtension)) { // file is image AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
singleFileContentsFrame.setVisibility(View.GONE); }
singleCodeContents.setVisibility(View.GONE); else if(response.code() == 403) {
pdfViewFrame.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
imageData = Base64.decode(response.body().getContent(), Base64.DEFAULT); Toasty.info(ctx, ctx.getString(R.string.authorizeError));
Drawable imageDrawable = new BitmapDrawable(getResources(), BitmapFactory.decodeByteArray(imageData, 0, imageData.length));
imageView.setImageDrawable(imageDrawable);
} }
else if(appUtil.sourceCodeExtension(fileExtension)) { // file is sourcecode else if(response.code() == 404) {
imageView.setVisibility(View.GONE); Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
singleFileContentsFrame.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.VISIBLE);
switch(tinyDb.getInt("fileviewerSourceCodeThemeId")) { }
case 1: else {
singleCodeContents.setTheme(Theme.ARDUINO_LIGHT);
break;
case 2:
singleCodeContents.setTheme(Theme.GITHUB);
break;
case 3:
singleCodeContents.setTheme(Theme.FAR);
break;
case 4:
singleCodeContents.setTheme(Theme.IR_BLACK);
break;
case 5:
singleCodeContents.setTheme(Theme.ANDROID_STUDIO);
break;
default:
singleCodeContents.setTheme(Theme.MONOKAI_SUBLIME);
}
singleCodeContents.setSource(appUtil.decodeBase64(response.body().getContent())); Toasty.info(getApplicationContext(), getString(R.string.labelGeneralError));
} }
else if(appUtil.pdfExtension(fileExtension)) { // file is pdf
imageView.setVisibility(View.GONE); }
singleFileContentsFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.VISIBLE);
pdfNightMode = tinyDb.getBoolean("enablePdfMode"); @Override
public void onFailure(@NonNull Call<Files> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
decodedPdf = Base64.decode(response.body().getContent(), Base64.DEFAULT); }
pdfView.fromBytes(decodedPdf).enableSwipe(true).swipeHorizontal(false).enableDoubletap(true).defaultPage(0).enableAnnotationRendering(false).password(null).scrollHandle(null).enableAntialiasing(true).spacing(0).autoSpacing(true).pageFitPolicy(FitPolicy.WIDTH).fitEachPage(true).pageSnap(false).pageFling(true).nightMode(pdfNightMode).load();
} private void initCloseListener() {
else if(appUtil.excludeFilesInFileViewerExtension(fileExtension)) { // files need to be excluded onClickListener = new View.OnClickListener() {
@Override
imageView.setVisibility(View.GONE); public void onClick(View view) {
singleCodeContents.setVisibility(View.GONE); getIntent().removeExtra("singleFileName");
pdfViewFrame.setVisibility(View.GONE); finish();
singleFileContentsFrame.setVisibility(View.VISIBLE); }
};
singleFileContents.setText(getResources().getString(R.string.excludeFilesInFileviewer)); }
singleFileContents.setGravity(Gravity.CENTER);
singleFileContents.setTypeface(null, Typeface.BOLD);
}
else { // file type not known - plain text view
imageView.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setText(appUtil.decodeBase64(response.body().getContent()));
}
}
else {
singleFileContents.setText("");
mProgressBar.setVisibility(View.GONE);
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<Files> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
inflater.inflate(R.menu.files_view_menu, menu);
String fileExtension = FileUtils.getExtension(singleFileName);
if(!fileExtension.equalsIgnoreCase("md")) {
menu.getItem(0).setVisible(false);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch(id) {
case android.R.id.home:
finish();
return true;
case R.id.genericMenu:
BottomSheetFileViewerFragment bottomSheet = new BottomSheetFileViewerFragment();
bottomSheet.show(getSupportFragmentManager(), "fileViewerBottomSheet");
return true;
case R.id.markdown:
final Markwon markwon = Markwon.builder(Objects.requireNonNull(ctx)).usePlugin(CorePlugin.create())
.usePlugin(ImagesPlugin.create(plugin -> {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = ctx.getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
ctx.getPackageName());
final Drawable drawable = ctx.getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(drawable -> null);
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(ctx.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(ctx.getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder.codeTextColor(tinyDb.getInt("codeBlockColor")).codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(ctx))
.usePlugin(TaskListPlugin.create(ctx))
.usePlugin(HtmlPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())
.build();
if(!tinyDb.getBoolean("enableMarkdownInFileView")) {
singleCodeContents.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setVisibility(View.VISIBLE);
Spanned bodyWithMD = markwon.toMarkdown(appUtil.decodeBase64(tinyDb.getString("downloadFileContents")));
markwon.setParsedMarkdown(singleFileContents, bodyWithMD);
tinyDb.putBoolean("enableMarkdownInFileView", true);
}
else {
singleCodeContents.setVisibility(View.VISIBLE);
singleFileContentsFrame.setVisibility(View.GONE);
singleFileContents.setVisibility(View.GONE);
singleCodeContents.setSource(appUtil.decodeBase64(tinyDb.getString("downloadFileContents")));
tinyDb.putBoolean("enableMarkdownInFileView", false);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onButtonClicked(String text) {
if("downloadFile".equals(text)) {
requestFileDownload();
}
if("deleteFile".equals(text)) {
String fileExtension = FileUtils.getExtension(singleFileName);
String data = appUtil.decodeBase64(tinyDb.getString("downloadFileContents"));
Intent intent = new Intent(ctx, CreateFileActivity.class);
intent.putExtra("fileAction", 1);
intent.putExtra("filePath", singleFileName);
intent.putExtra("fileSha", fileSha);
if(!appUtil.imageExtension(fileExtension)) {
intent.putExtra("fileContents", data);
}
else {
intent.putExtra("fileContents", "");
}
ctx.startActivity(intent);
}
if("editFile".equals(text)) {
String fileExtension = FileUtils.getExtension(singleFileName);
String data = appUtil.decodeBase64(tinyDb.getString("downloadFileContents"));
Intent intent = new Intent(ctx, CreateFileActivity.class);
intent.putExtra("fileAction", 2);
intent.putExtra("filePath", singleFileName);
intent.putExtra("fileSha", fileSha);
if(!appUtil.imageExtension(fileExtension)) {
intent.putExtra("fileContents", data);
}
else {
intent.putExtra("fileContents", "");
}
ctx.startActivity(intent);
}
}
private void requestFileDownload() {
if(!tinyDb.getString("downloadFileContents").isEmpty()) {
int CREATE_REQUEST_CODE = 40;
File outputFileName = new File(tinyDb.getString("downloadFileName"));
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_TITLE, outputFileName.getName());
startActivityForResult(intent, CREATE_REQUEST_CODE);
}
else {
Toasty.warning(ctx, getString(R.string.waitLoadingDownloadFile));
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 40 && resultCode == RESULT_OK) {
try {
assert data != null;
Uri uri = data.getData();
assert uri != null;
OutputStream outputStream = getContentResolver().openOutputStream(uri);
byte[] dataAsBytes = Base64.decode(tinyDb.getString("downloadFileContents"), 0);
assert outputStream != null;
outputStream.write(dataAsBytes);
outputStream.close();
Toasty.success(ctx, getString(R.string.downloadFileSaved));
}
catch(IOException e) {
Log.e("errorFileDownloading", Objects.requireNonNull(e.getMessage()));
}
}
}
private void initCloseListener() {
onClickListener = view -> {
getIntent().removeExtra("singleFileName");
finish();
};
}
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,28 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.annotation.SuppressLint; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import androidx.annotation.NonNull; import android.widget.Button;
import com.google.gson.JsonElement; import android.widget.ImageView;
import android.widget.TextView;
import com.hendraanggrian.appcompat.socialview.Mention; import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter; import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityMergePullRequestBinding;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Collaborators; import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.MergePullRequest; import org.mian.gitnex.models.MergePullRequest;
import org.mian.gitnex.models.MergePullRequestSpinner; import org.mian.gitnex.util.AppUtil;
import java.util.ArrayList; import org.mian.gitnex.util.TinyDB;
import java.util.List; import java.util.List;
import okhttp3.ResponseBody; import okhttp3.ResponseBody;
import retrofit2.Call; import retrofit2.Call;
@ -35,347 +33,226 @@ import retrofit2.Response;
* Author M M Arif * Author M M Arif
*/ */
public class MergePullRequestActivity extends BaseActivity { public class MergePullRequestActivity extends AppCompatActivity {
private View.OnClickListener onClickListener; public ImageView closeActivity;
final Context ctx = this; private View.OnClickListener onClickListener;
private Context appCtx;
private ActivityMergePullRequestBinding viewBinding;
private ArrayAdapter<Mention> defaultMentionAdapter; final Context ctx = this;
private String Do;
@Override private SocialAutoCompleteTextView mergePR;
protected int getLayoutResourceId() { private ArrayAdapter<Mention> defaultMentionAdapter;
private Button mergeButton;
return R.layout.activity_merge_pull_request; @Override
} protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_merge_pull_request);
@SuppressLint("SetTextI18n") boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
@Override TinyDB tinyDb = new TinyDB(getApplicationContext());
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); mergePR = findViewById(R.id.mergePR);
appCtx = getApplicationContext(); mergePR.setShowSoftInputOnFocus(true);
viewBinding = ActivityMergePullRequestBinding.inflate(getLayoutInflater()); defaultMentionAdapter = new MentionArrayAdapter<>(this);
View view = viewBinding.getRoot(); loadCollaboratorsList();
setContentView(view);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); mergePR.setMentionAdapter(defaultMentionAdapter);
TinyDB tinyDb = new TinyDB(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); closeActivity = findViewById(R.id.close);
TextView toolbar_title = findViewById(R.id.toolbar_title);
viewBinding.mergeTitle.requestFocus(); if(!tinyDb.getString("issueTitle").isEmpty()) {
assert imm != null; toolbar_title.setText(tinyDb.getString("issueTitle"));
imm.showSoftInput(viewBinding.mergeTitle, InputMethodManager.SHOW_IMPLICIT); }
setMergeAdapter(); initCloseListener();
closeActivity.setOnClickListener(onClickListener);
viewBinding.mergeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { mergeButton = findViewById(R.id.mergeButton);
@Override if(!connToInternet) {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
MergePullRequestSpinner mergeId = (MergePullRequestSpinner) parent.getSelectedItem(); disableProcessButton();
Do = mergeId.getId();
} } else {
@Override mergeButton.setOnClickListener(mergePullRequest);
public void onNothingSelected(AdapterView<?> parent) {
} }
}); }
defaultMentionAdapter = new MentionArrayAdapter<>(this); public void loadCollaboratorsList() {
loadCollaboratorsList();
viewBinding.mergeDescription.setMentionAdapter(defaultMentionAdapter); final TinyDB tinyDb = new TinyDB(getApplicationContext());
if(!tinyDb.getString("issueTitle").isEmpty()) { final String instanceUrl = tinyDb.getString("instanceUrl");
viewBinding.toolbarTitle.setText(tinyDb.getString("issueTitle")); final String loginUid = tinyDb.getString("loginUid");
viewBinding.mergeTitle.setText(tinyDb.getString("issueTitle") + " (#" + tinyDb.getString("issueNumber") + ")"); final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
} String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
initCloseListener(); Call<List<Collaborators>> call = RetrofitClient
viewBinding.close.setOnClickListener(onClickListener); .getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
// if gitea version is greater/equal(1.12.0) than user installed version (installed.higherOrEqual(compareVer)) call.enqueue(new Callback<List<Collaborators>>() {
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
viewBinding.deleteBranch.setVisibility(View.VISIBLE);
}
if(tinyDb.getString("prMergeable").equals("false")) { @Override
disableProcessButton(); public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
viewBinding.mergeInfoDisabledMessage.setVisibility(View.VISIBLE);
}
else {
viewBinding.mergeInfoDisabledMessage.setVisibility(View.GONE);
}
if(tinyDb.getString("prIsFork").equals("true")) { if (response.isSuccessful()) {
viewBinding.deleteBranchForkInfo.setVisibility(View.VISIBLE);
}
else {
viewBinding.deleteBranchForkInfo.setVisibility(View.GONE);
}
if(!connToInternet) { assert response.body() != null;
String fullName = "";
for (int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(
new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
disableProcessButton(); }
} else {
else {
viewBinding.mergeButton.setOnClickListener(mergePullRequest); Log.i("onResponse", String.valueOf(response.code()));
}
} }
private void setMergeAdapter() { }
TinyDB tinyDb = new TinyDB(appCtx); @Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.toString());
}
ArrayList<MergePullRequestSpinner> mergeList = new ArrayList<>(); });
}
mergeList.add(new MergePullRequestSpinner("merge", getResources().getString(R.string.mergeOptionMerge))); private void initCloseListener() {
mergeList.add(new MergePullRequestSpinner("rebase", getResources().getString(R.string.mergeOptionRebase))); onClickListener = new View.OnClickListener() {
mergeList.add(new MergePullRequestSpinner("rebase-merge", getResources().getString(R.string.mergeOptionRebaseCommit))); @Override
// squash merge works only on gitea > v1.11.4 due to a bug public void onClick(View view) {
if(new Version(tinyDb.getString("giteaVersion")).higher("1.11.4")) { finish();
mergeList.add(new MergePullRequestSpinner("squash", getResources().getString(R.string.mergeOptionSquash))); }
} };
}
ArrayAdapter<MergePullRequestSpinner> adapter = new ArrayAdapter<>(MergePullRequestActivity.this, R.layout.spinner_item, mergeList); private View.OnClickListener mergePullRequest = new View.OnClickListener() {
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item); public void onClick(View v) {
viewBinding.mergeSpinner.setAdapter(adapter); processMergePullRequest();
}
};
} private void processMergePullRequest() {
public void loadCollaboratorsList() { String mergePRDT = mergePR.getText().toString();
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
final TinyDB tinyDb = new TinyDB(appCtx); if(!connToInternet) {
final String instanceUrl = tinyDb.getString("instanceUrl"); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
final String loginUid = tinyDb.getString("loginUid"); return;
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName); }
call.enqueue(new Callback<List<Collaborators>>() { disableProcessButton();
String doWhat = "merge";
mergeFunction(doWhat, mergePRDT);
@Override }
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if(response.isSuccessful()) { private void mergeFunction(String doWhat, String mergePRDT) {
assert response.body() != null; final TinyDB tinyDb = new TinyDB(getApplicationContext());
String fullName = "";
for(int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
} final String instanceUrl = tinyDb.getString("instanceUrl");
else { final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int prIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
Log.i("onResponse", String.valueOf(response.code())); MergePullRequest mergePR = new MergePullRequest(doWhat, mergePRDT, null);
} Call<ResponseBody> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.mergePullRequest(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, prIndex, mergePR);
} call.enqueue(new Callback<ResponseBody>() {
@Override @Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) { public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
Log.i("onFailure", t.toString()); if(response.code() == 200) {
}
}); Toasty.info(getApplicationContext(), getString(R.string.mergePRSuccessMsg));
} tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
finish();
private void initCloseListener() { }
else if(response.code() == 401) {
onClickListener = view -> finish(); enableProcessButton();
} AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
private View.OnClickListener mergePullRequest = v -> processMergePullRequest(); }
else if(response.code() == 404) {
private void processMergePullRequest() { enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.mergePR404ErrorMsg));
String mergePRDesc = viewBinding.mergeDescription.getText().toString(); }
String mergePRTitle = viewBinding.mergeTitle.getText().toString(); else {
boolean deleteBranch = viewBinding.deleteBranch.isChecked();
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.genericError));
if(!connToInternet) { }
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); }
return;
} @Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
disableProcessButton(); });
mergeFunction(Do, mergePRDesc, mergePRTitle, deleteBranch);
} }
private void mergeFunction(String Do, String mergePRDT, String mergeTitle, boolean deleteBranch) { private void disableProcessButton() {
final TinyDB tinyDb = new TinyDB(appCtx); mergeButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
mergeButton.setBackground(shape);
final String instanceUrl = tinyDb.getString("instanceUrl"); }
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int prIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
MergePullRequest mergePR = new MergePullRequest(Do, mergePRDT, mergeTitle); private void enableProcessButton() {
Call<ResponseBody> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().mergePullRequest(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, prIndex, mergePR); mergeButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
mergeButton.setBackground(shape);
call.enqueue(new Callback<ResponseBody>() { }
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
if(response.code() == 200) {
if(deleteBranch) {
if(tinyDb.getString("prIsFork").equals("true")) {
String repoFullName = tinyDb.getString("prForkFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
deleteBranchFunction(repoOwner, repoName);
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
finish();
}
else {
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
deleteBranchFunction(repoOwner, repoName);
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
finish();
}
}
else {
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
tinyDb.putBoolean("prMerged", true);
tinyDb.putBoolean("resumePullRequests", true);
finish();
}
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.mergePR404ErrorMsg));
}
else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void deleteBranchFunction(String repoOwner, String repoName) {
TinyDB tinyDb = new TinyDB(appCtx);
String instanceUrl = tinyDb.getString("instanceUrl");
String loginUid = tinyDb.getString("loginUid");
String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String branchName = tinyDb.getString("prHeadBranch");
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.deleteBranch(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 204) {
Log.i("deleteBranch", "Branch deleted successfully");
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void disableProcessButton() {
viewBinding.mergeButton.setEnabled(false);
}
private void enableProcessButton() {
viewBinding.mergeButton.setEnabled(true);
}
} }

View File

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

View File

@ -1,34 +1,34 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.app.DatePickerDialog; import android.app.DatePickerDialog;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.DatePicker; import android.widget.DatePicker;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Milestones; import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.Calendar; import java.util.Calendar;
import retrofit2.Call;
import retrofit2.Callback;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class CreateMilestoneActivity extends BaseActivity implements View.OnClickListener { public class NewMilestoneActivity extends AppCompatActivity implements View.OnClickListener {
private EditText milestoneDueDate; private EditText milestoneDueDate;
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
@ -36,22 +36,13 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
private EditText milestoneDescription; private EditText milestoneDescription;
private Button createNewMilestoneButton; private Button createNewMilestoneButton;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_new_milestone;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_new_milestone);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
milestoneDueDate = findViewById(R.id.milestoneDueDate); milestoneDueDate = findViewById(R.id.milestoneDueDate);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = findViewById(R.id.close);
@ -59,10 +50,6 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
milestoneTitle = findViewById(R.id.milestoneTitle); milestoneTitle = findViewById(R.id.milestoneTitle);
milestoneDescription = findViewById(R.id.milestoneDescription); milestoneDescription = findViewById(R.id.milestoneDescription);
milestoneTitle.requestFocus();
assert imm != null;
imm.showSoftInput(milestoneTitle, InputMethodManager.SHOW_IMPLICIT);
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
milestoneDueDate.setOnClickListener(this); milestoneDueDate.setOnClickListener(this);
@ -70,21 +57,30 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
if(!connToInternet) { if(!connToInternet) {
createNewMilestoneButton.setEnabled(false); createNewMilestoneButton.setEnabled(false);
} GradientDrawable shape = new GradientDrawable();
else { shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewMilestoneButton.setBackground(shape);
} else {
createNewMilestoneButton.setOnClickListener(createMilestoneListener); createNewMilestoneButton.setOnClickListener(createMilestoneListener);
} }
} }
private View.OnClickListener createMilestoneListener = v -> processNewMilestone(); private View.OnClickListener createMilestoneListener = new View.OnClickListener() {
public void onClick(View v) {
processNewMilestone();
}
};
private void processNewMilestone() { private void processNewMilestone() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
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];
@ -100,14 +96,14 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
if(!connToInternet) { if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return; return;
} }
if(newMilestoneTitle.equals("")) { if(newMilestoneTitle.equals("")) {
Toasty.error(ctx, getString(R.string.milestoneNameErrorEmpty)); Toasty.info(getApplicationContext(), getString(R.string.milestoneNameErrorEmpty));
return; return;
} }
@ -115,26 +111,22 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
if(!newMilestoneDescription.equals("")) { if(!newMilestoneDescription.equals("")) {
if (appUtil.charactersLength(newMilestoneDescription) > 255) { if (appUtil.charactersLength(newMilestoneDescription) > 255) {
Toasty.warning(ctx, getString(R.string.milestoneDescError)); Toasty.info(getApplicationContext(), getString(R.string.milestoneDescError));
return; return;
} }
} }
String finalMilestoneDueDate = null; if(newMilestoneDueDate.equals("")) {
if(!newMilestoneDueDate.isEmpty()) {
finalMilestoneDueDate = (AppUtil.customDateCombine(AppUtil.customDateFormat(newMilestoneDueDate))); Toasty.info(getApplicationContext(), getString(R.string.milestoneDateEmpty));
}
else if (new Version(tinyDb.getString("giteaVersion")).less("1.10.0")) {
// if Gitea version is less than 1.10.0 DueDate is required
Toasty.warning(ctx, getString(R.string.milestoneDateEmpty));
return; return;
} }
disableProcessButton(); disableProcessButton();
createNewMilestone(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, newMilestoneTitle, newMilestoneDescription, finalMilestoneDueDate); String finalMilestoneDueDate = (AppUtil.customDateCombine(AppUtil.customDateFormat(newMilestoneDueDate)));
createNewMilestone(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, newMilestoneTitle, newMilestoneDescription, finalMilestoneDueDate);
} }
@ -145,7 +137,7 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
Call<Milestones> call; Call<Milestones> call;
call = RetrofitClient call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.createMilestone(token, repoOwner, repoName, createMilestone); .createMilestone(token, repoOwner, repoName, createMilestone);
@ -157,9 +149,9 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
if(response.isSuccessful()) { if(response.isSuccessful()) {
if(response.code() == 201) { if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("milestoneCreated", true); tinyDb.putBoolean("milestoneCreated", true);
Toasty.success(ctx, getString(R.string.milestoneCreated)); Toasty.info(getApplicationContext(), getString(R.string.milestoneCreated));
enableProcessButton(); enableProcessButton();
finish(); finish();
@ -177,7 +169,7 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
else { else {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, getString(R.string.milestoneCreatedError)); Toasty.info(getApplicationContext(), getString(R.string.milestoneCreatedError));
} }
@ -219,18 +211,32 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
} }
private void initCloseListener() { private void initCloseListener() {
onClickListener = new View.OnClickListener() {
onClickListener = view -> finish(); @Override
public void onClick(View view) {
finish();
}
};
} }
private void disableProcessButton() { private void disableProcessButton() {
createNewMilestoneButton.setEnabled(false); createNewMilestoneButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewMilestoneButton.setBackground(shape);
} }
private void enableProcessButton() { private void enableProcessButton() {
createNewMilestoneButton.setEnabled(true); createNewMilestoneButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createNewMilestoneButton.setBackground(shape);
} }
} }

View File

@ -1,22 +1,23 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserOrganizations; import org.mian.gitnex.models.UserOrganizations;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -24,7 +25,7 @@ import retrofit2.Callback;
* Author M M Arif * Author M M Arif
*/ */
public class CreateOrganizationActivity extends BaseActivity { public class NewOrganizationActivity extends AppCompatActivity {
public ImageView closeActivity; public ImageView closeActivity;
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
@ -33,31 +34,18 @@ public class CreateOrganizationActivity extends BaseActivity {
private EditText orgName; private EditText orgName;
private EditText orgDesc; private EditText orgDesc;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_new_organization;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_new_organization);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
closeActivity = findViewById(R.id.close); closeActivity = findViewById(R.id.close);
orgName = findViewById(R.id.newOrganizationName); orgName = findViewById(R.id.newOrganizationName);
orgDesc = findViewById(R.id.newOrganizationDescription); orgDesc = findViewById(R.id.newOrganizationDescription);
orgName.requestFocus();
assert imm != null;
imm.showSoftInput(orgName, InputMethodManager.SHOW_IMPLICIT);
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
@ -66,10 +54,15 @@ public class CreateOrganizationActivity extends BaseActivity {
if(!connToInternet) { if(!connToInternet) {
createOrganizationButton.setEnabled(false); createOrganizationButton.setEnabled(false);
} GradientDrawable shape = new GradientDrawable();
else { shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createOrganizationButton.setBackground(shape);
} else {
createOrganizationButton.setOnClickListener(createOrgListener); createOrganizationButton.setOnClickListener(createOrgListener);
} }
} }
@ -91,9 +84,9 @@ public class CreateOrganizationActivity extends BaseActivity {
private void processNewOrganization() { private void processNewOrganization() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
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");
@ -103,7 +96,7 @@ public class CreateOrganizationActivity extends BaseActivity {
if(!connToInternet) { if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return; return;
} }
@ -111,7 +104,7 @@ public class CreateOrganizationActivity extends BaseActivity {
if(!newOrgDesc.equals("")) { if(!newOrgDesc.equals("")) {
if (appUtil.charactersLength(newOrgDesc) > 255) { if (appUtil.charactersLength(newOrgDesc) > 255) {
Toasty.warning(ctx, getString(R.string.orgDescError)); Toasty.info(getApplicationContext(), getString(R.string.orgDescError));
return; return;
} }
@ -119,18 +112,18 @@ public class CreateOrganizationActivity extends BaseActivity {
if(newOrgName.equals("")) { if(newOrgName.equals("")) {
Toasty.error(ctx, getString(R.string.orgNameErrorEmpty)); Toasty.info(getApplicationContext(), getString(R.string.orgNameErrorEmpty));
} }
else if(!appUtil.checkStrings(newOrgName)) { else if(!appUtil.checkStrings(newOrgName)) {
Toasty.warning(ctx, getString(R.string.orgNameErrorInvalid)); Toasty.info(getApplicationContext(), getString(R.string.orgNameErrorInvalid));
} }
else { else {
disableProcessButton(); disableProcessButton();
createNewOrganization(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), newOrgName, newOrgDesc); createNewOrganization(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), newOrgName, newOrgDesc);
} }
@ -141,7 +134,7 @@ public class CreateOrganizationActivity extends BaseActivity {
UserOrganizations createOrganization = new UserOrganizations(orgName, null, orgDesc, null, null); UserOrganizations createOrganization = new UserOrganizations(orgName, null, orgDesc, null, null);
Call<UserOrganizations> call = RetrofitClient Call<UserOrganizations> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.createNewOrganization(token, createOrganization); .createNewOrganization(token, createOrganization);
@ -152,10 +145,10 @@ public class CreateOrganizationActivity extends BaseActivity {
if(response.code() == 201) { if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("orgCreated", true); tinyDb.putBoolean("orgCreated", true);
enableProcessButton(); enableProcessButton();
Toasty.success(ctx, getString(R.string.orgCreated)); Toasty.info(getApplicationContext(), getString(R.string.orgCreated));
finish(); finish();
} }
@ -171,24 +164,24 @@ public class CreateOrganizationActivity extends BaseActivity {
else if(response.code() == 409) { else if(response.code() == 409) {
enableProcessButton(); enableProcessButton();
Toasty.warning(ctx, getString(R.string.orgExistsError)); Toasty.info(getApplicationContext(), getString(R.string.orgExistsError));
} }
else if(response.code() == 422) { else if(response.code() == 422) {
enableProcessButton(); enableProcessButton();
Toasty.warning(ctx, getString(R.string.orgExistsError)); Toasty.info(getApplicationContext(), getString(R.string.orgExistsError));
} }
else { else {
if(response.code() == 404) { if(response.code() == 404) {
enableProcessButton(); enableProcessButton();
Toasty.warning(ctx, getString(R.string.apiNotFound)); Toasty.info(getApplicationContext(), getString(R.string.apiNotFound));
} }
else { else {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, getString(R.string.orgCreatedError)); Toasty.info(getApplicationContext(), getString(R.string.orgCreatedError));
} }
} }
@ -207,11 +200,21 @@ public class CreateOrganizationActivity extends BaseActivity {
private void disableProcessButton() { private void disableProcessButton() {
createOrganizationButton.setEnabled(false); createOrganizationButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createOrganizationButton.setBackground(shape);
} }
private void enableProcessButton() { private void enableProcessButton() {
createOrganizationButton.setEnabled(true); createOrganizationButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createOrganizationButton.setBackground(shape);
} }
} }

View File

@ -1,10 +1,13 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.content.Context; import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
@ -12,20 +15,17 @@ import android.widget.CheckBox;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Spinner; import android.widget.Spinner;
import androidx.annotation.NonNull;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.OrgOwner; import org.mian.gitnex.models.OrgOwner;
import org.mian.gitnex.models.OrganizationRepository; import org.mian.gitnex.models.OrganizationRepository;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.regex.Pattern;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -33,7 +33,7 @@ import retrofit2.Callback;
* Author M M Arif * Author M M Arif
*/ */
public class CreateRepoActivity extends BaseActivity { public class NewRepoActivity extends AppCompatActivity {
public ImageView closeActivity; public ImageView closeActivity;
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
@ -43,50 +43,33 @@ public class CreateRepoActivity extends BaseActivity {
private EditText repoDesc; private EditText repoDesc;
private CheckBox repoAccess; private CheckBox repoAccess;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
List<OrgOwner> organizationsList = new ArrayList<>(); List<OrgOwner> orgsList = new ArrayList<>();
//https://github.com/go-gitea/gitea/blob/52cfd2743c0e85b36081cf80a850e6a5901f1865/models/repo.go#L964-L967
final List<String> reservedRepoNames = Arrays.asList(".", "..");
final Pattern reservedRepoPatterns = Pattern.compile("\\.(git|wiki)$");
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_new_repo;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_new_repo);
boolean connToInternet = AppUtil.hasNetworkConnection(ctx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
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 userLogin = tinyDb.getString("userLogin"); final String userLogin = tinyDb.getString("userLogin");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
closeActivity = findViewById(R.id.close); closeActivity = findViewById(R.id.close);
repoName = findViewById(R.id.newRepoName); repoName = findViewById(R.id.newRepoName);
repoDesc = findViewById(R.id.newRepoDescription); repoDesc = findViewById(R.id.newRepoDescription);
repoAccess = findViewById(R.id.newRepoPrivate); repoAccess = findViewById(R.id.newRepoPrivate);
repoName.requestFocus();
assert imm != null;
imm.showSoftInput(repoName, InputMethodManager.SHOW_IMPLICIT);
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
spinner = findViewById(R.id.ownerSpinner); spinner = findViewById(R.id.ownerSpinner);
getOrganizations(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), userLogin); spinner.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
getOrgs(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), userLogin);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
@ -105,11 +88,14 @@ public class CreateRepoActivity extends BaseActivity {
if(!connToInternet) { if(!connToInternet) {
disableProcessButton(); disableProcessButton();
} }
else { else {
createRepo.setOnClickListener(createRepoListener); createRepo.setOnClickListener(createRepoListener);
} }
} }
private View.OnClickListener createRepoListener = new View.OnClickListener() { private View.OnClickListener createRepoListener = new View.OnClickListener() {
@ -120,9 +106,9 @@ public class CreateRepoActivity extends BaseActivity {
private void processNewRepo() { private void processNewRepo() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil(); AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
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");
@ -134,39 +120,38 @@ public class CreateRepoActivity extends BaseActivity {
if(!connToInternet) { if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return; return;
} }
if(!newRepoDesc.equals("")) { if(!newRepoDesc.equals("")) {
if (appUtil.charactersLength(newRepoDesc) > 255) { if (appUtil.charactersLength(newRepoDesc) > 255) {
Toasty.warning(ctx, getString(R.string.repoDescError)); Toasty.info(getApplicationContext(), getString(R.string.repoDescError));
return; return;
} }
} }
if(newRepoName.equals("")) { if(newRepoName.equals("")) {
Toasty.error(ctx, getString(R.string.repoNameErrorEmpty)); Toasty.info(getApplicationContext(), getString(R.string.repoNameErrorEmpty));
} }
else if(!appUtil.checkStrings(newRepoName)) { else if(!appUtil.checkStrings(newRepoName)) {
Toasty.warning(ctx, getString(R.string.repoNameErrorInvalid)); Toasty.info(getApplicationContext(), getString(R.string.repoNameErrorInvalid));
}
else if (reservedRepoNames.contains(newRepoName)) {
Toasty.warning(ctx, getString(R.string.repoNameErrorReservedName));
}
else if (reservedRepoPatterns.matcher(newRepoName).find()) {
Toasty.warning(ctx, getString(R.string.repoNameErrorReservedPatterns));
} }
else { else {
//Log.i("repoOwner", String.valueOf(repoOwner));
disableProcessButton(); disableProcessButton();
createNewRepository(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), loginUid, newRepoName, newRepoDesc, repoOwner, newRepoAccess); createNewRepository(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), loginUid, newRepoName, newRepoDesc, repoOwner, newRepoAccess);
} }
} }
private void createNewRepository(final String instanceUrl, final String token, String loginUid, String repoName, String repoDesc, String repoOwner, boolean isPrivate) { private void createNewRepository(final String instanceUrl, final String token, String loginUid, String repoName, String repoDesc, String repoOwner, boolean isPrivate) {
@ -177,16 +162,18 @@ public class CreateRepoActivity extends BaseActivity {
if(repoOwner.equals(loginUid)) { if(repoOwner.equals(loginUid)) {
call = RetrofitClient call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.createNewUserRepository(token, createRepository); .createNewUserRepository(token, createRepository);
} }
else { else {
call = RetrofitClient call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.createNewUserOrgRepository(token, repoOwner, createRepository); .createNewUserOrgRepository(token, repoOwner, createRepository);
} }
call.enqueue(new Callback<OrganizationRepository>() { call.enqueue(new Callback<OrganizationRepository>() {
@ -196,9 +183,9 @@ public class CreateRepoActivity extends BaseActivity {
if(response.code() == 201) { if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("repoCreated", true); tinyDb.putBoolean("repoCreated", true);
Toasty.success(ctx, getString(R.string.repoCreated)); Toasty.info(getApplicationContext(), getString(R.string.repoCreated));
enableProcessButton(); enableProcessButton();
finish(); finish();
} }
@ -209,35 +196,36 @@ public class CreateRepoActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
} }
else if(response.code() == 409) { else if(response.code() == 409) {
enableProcessButton(); enableProcessButton();
Toasty.warning(ctx, getString(R.string.repoExistsError)); Toasty.info(getApplicationContext(), getString(R.string.repoExistsError));
} }
else { else {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, getString(R.string.repoCreatedError)); Toasty.info(getApplicationContext(), getString(R.string.repoCreatedError));
} }
} }
@Override @Override
public void onFailure(@NonNull Call<OrganizationRepository> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<OrganizationRepository> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString()); Log.e("onFailure", t.toString());
enableProcessButton(); enableProcessButton();
} }
}); });
} }
private void getOrganizations(String instanceUrl, String instanceToken, final String userLogin) { private void getOrgs(String instanceUrl, String instanceToken, final String userLogin) {
TinyDB tinyDb = new TinyDB(appCtx);
Call<List<OrgOwner>> call = RetrofitClient Call<List<OrgOwner>> call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.getOrgOwners(instanceToken); .getOrgOwners(instanceToken);
@ -249,43 +237,26 @@ public class CreateRepoActivity extends BaseActivity {
if(response.isSuccessful()) { if(response.isSuccessful()) {
if(response.code() == 200) { if(response.code() == 200) {
int organizationId = 0; List<OrgOwner> orgsList_ = response.body();
List<OrgOwner> organizationsList_ = response.body(); orgsList.add(new OrgOwner(userLogin));
assert orgsList_ != null;
organizationsList.add(new OrgOwner(userLogin)); if(orgsList_.size() > 0) {
assert organizationsList_ != null; for (int i = 0; i < orgsList_.size(); i++) {
if(organizationsList_.size() > 0) {
for (int i = 0; i < organizationsList_.size(); i++) {
if(!tinyDb.getString("organizationId").isEmpty()) {
if (Integer.parseInt(tinyDb.getString("organizationId")) == organizationsList_.get(i).getId()) {
organizationId = i + 1;
}
}
OrgOwner data = new OrgOwner( OrgOwner data = new OrgOwner(
organizationsList_.get(i).getUsername() orgsList_.get(i).getUsername()
); );
organizationsList.add(data); orgsList.add(data);
} }
} }
ArrayAdapter<OrgOwner> adapter = new ArrayAdapter<>(CreateRepoActivity.this, ArrayAdapter<OrgOwner> adapter = new ArrayAdapter<>(getApplicationContext(),
R.layout.spinner_item, organizationsList); R.layout.spinner_item, orgsList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item); adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
spinner.setAdapter(adapter); spinner.setAdapter(adapter);
if (tinyDb.getBoolean("organizationAction") & organizationId != 0) {
spinner.setSelection(organizationId);
tinyDb.putBoolean("organizationAction", false);
}
enableProcessButton(); enableProcessButton();
} }
@ -297,32 +268,47 @@ public class CreateRepoActivity extends BaseActivity {
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
} }
} }
@Override @Override
public void onFailure(@NonNull Call<List<OrgOwner>> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<List<OrgOwner>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString()); Log.e("onFailure", t.toString());
enableProcessButton(); enableProcessButton();
} }
}); });
} }
private void initCloseListener() { private void initCloseListener() {
onClickListener = new View.OnClickListener() {
onClickListener = view -> finish(); @Override
public void onClick(View view) {
finish();
}
};
} }
private void disableProcessButton() { private void disableProcessButton() {
createRepo.setEnabled(false); createRepo.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createRepo.setBackground(shape);
} }
private void enableProcessButton() { private void enableProcessButton() {
createRepo.setEnabled(true); createRepo.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createRepo.setBackground(shape);
} }
} }

View File

@ -1,17 +1,10 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.content.Context;
import android.content.Intent; 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.util.TinyDB;
import org.mian.gitnex.helpers.PathsHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.net.URI;
import java.net.URISyntaxException;
import io.mikael.urlbuilder.UrlBuilder;
/** /**
* Author M M Arif * Author M M Arif
@ -19,35 +12,23 @@ import io.mikael.urlbuilder.UrlBuilder;
public class OpenRepoInBrowserActivity extends AppCompatActivity { public class OpenRepoInBrowserActivity extends AppCompatActivity {
private Context appCtx;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
try { TinyDB tinyDb = new TinyDB(getApplicationContext());
String instanceUrlWithProtocol = "https://" + tinyDb.getString("instanceUrlRaw");
if (!tinyDb.getString("instanceUrlWithProtocol").isEmpty()) {
instanceUrlWithProtocol = tinyDb.getString("instanceUrlWithProtocol");
}
URI instanceUrl = new URI(UrlBuilder.fromString(tinyDb.getString("instanceUrl")) String repoFullNameBrowser = getIntent().getStringExtra("repoFullNameBrowser");
.withPath("/") Uri url = Uri.parse(instanceUrlWithProtocol + "/" + repoFullNameBrowser);
.toString()); Intent i = new Intent(Intent.ACTION_VIEW, url);
startActivity(i);
String browserPath = PathsHelper.join(instanceUrl.getPath(), getIntent().getStringExtra("repoFullNameBrowser")); 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

@ -1,108 +1,53 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.content.ClipData; import com.google.android.material.tabs.TabLayout;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter; import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager; import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout; import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.fragments.BottomSheetOrganizationFragment;
import org.mian.gitnex.fragments.MembersByOrgFragment; import org.mian.gitnex.fragments.MembersByOrgFragment;
import org.mian.gitnex.fragments.OrgBottomSheetFragment;
import org.mian.gitnex.fragments.OrganizationInfoFragment; import org.mian.gitnex.fragments.OrganizationInfoFragment;
import org.mian.gitnex.fragments.RepositoriesByOrgFragment; import org.mian.gitnex.fragments.RepositoriesByOrgFragment;
import org.mian.gitnex.fragments.TeamsByOrgFragment; import org.mian.gitnex.fragments.TeamsByOrgFragment;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.Objects; import java.util.Objects;
import io.mikael.urlbuilder.UrlBuilder;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class OrganizationDetailActivity extends BaseActivity implements BottomSheetOrganizationFragment.BottomSheetListener { public class OrgDetailActivity extends AppCompatActivity implements OrgBottomSheetFragment.BottomSheetListener {
final Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_org_detail;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_org_detail);
tinyDb = new TinyDB(appCtx);
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
String orgName = tinyDb.getString("orgName"); String orgName = tinyDb.getString("orgName");
Toolbar toolbar = findViewById(R.id.toolbar); Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(orgName); Objects.requireNonNull(getSupportActionBar()).setTitle(orgName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
OrganizationDetailActivity.SectionsPagerAdapter mSectionsPagerAdapter = new OrganizationDetailActivity.SectionsPagerAdapter(getSupportFragmentManager()); OrgDetailActivity.SectionsPagerAdapter mSectionsPagerAdapter = new OrgDetailActivity.SectionsPagerAdapter(getSupportFragmentManager());
ViewPager mViewPager = findViewById(R.id.container); ViewPager mViewPager = findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter); mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = findViewById(R.id.tabs); TabLayout tabLayout = findViewById(R.id.tabs);
Typeface myTypeface;
switch(tinyDb.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
break;
}
toolbarTitle.setTypeface(myTypeface);
toolbarTitle.setText(orgName);
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = vg.getChildCount();
for (int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
int tabChildCount = vgTab.getChildCount();
for (int i = 0; i < tabChildCount; i++) {
View tabViewChild = vgTab.getChildAt(i);
if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(myTypeface);
}
}
}
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager)); tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
@ -111,7 +56,6 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater(); MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.repo_dotted_menu, menu); inflater.inflate(R.menu.repo_dotted_menu, menu);
return true; return true;
@ -127,7 +71,7 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
finish(); finish();
return true; return true;
case R.id.repoMenu: case R.id.repoMenu:
BottomSheetOrganizationFragment bottomSheet = new BottomSheetOrganizationFragment(); OrgBottomSheetFragment bottomSheet = new OrgBottomSheetFragment();
bottomSheet.show(getSupportFragmentManager(), "orgBottomSheet"); bottomSheet.show(getSupportFragmentManager(), "orgBottomSheet");
return true; return true;
default: default:
@ -140,41 +84,27 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh
public void onButtonClicked(String text) { public void onButtonClicked(String text) {
switch (text) { switch (text) {
case "repository":
tinyDb.putBoolean("organizationAction", true);
startActivity(new Intent(OrganizationDetailActivity.this, CreateRepoActivity.class));
break;
case "team": case "team":
startActivity(new Intent(OrgDetailActivity.this, CreateTeamByOrgActivity.class));
startActivity(new Intent(OrganizationDetailActivity.this, CreateTeamByOrgActivity.class));
break; break;
case "copyOrgUrl":
String url = UrlBuilder.fromString(tinyDb.getString("instanceUrl"))
.withPath("/")
.toString();
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("orgUrl", url + tinyDb.getString("orgName"));
assert clipboard != null;
clipboard.setPrimaryClip(clip);
Toasty.info(ctx, ctx.getString(R.string.copyIssueUrlToastMsg));
break;
} }
//Log.i("clicked", text);
} }
public class SectionsPagerAdapter extends FragmentPagerAdapter { public class SectionsPagerAdapter extends FragmentPagerAdapter {
SectionsPagerAdapter(FragmentManager fm) { SectionsPagerAdapter(FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); super(fm);
} }
@NonNull @NonNull
@Override @Override
public Fragment getItem(int position) { public Fragment getItem(int position) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
String orgName; String orgName;
if(getIntent().getStringExtra("orgName") != null || !Objects.equals(getIntent().getStringExtra("orgName"), "")) { if(getIntent().getStringExtra("orgName") != null || !getIntent().getStringExtra("orgName").equals("")) {
orgName = getIntent().getStringExtra("orgName"); orgName = getIntent().getStringExtra("orgName");
} }
else { else {

View File

@ -0,0 +1,101 @@
package org.mian.gitnex.activities;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.TeamMembersByOrgAdapter;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.TeamMembersByOrgViewModel;
import java.util.List;
/**
* Author M M Arif
*/
public class OrgTeamMembersActivity extends AppCompatActivity {
private TextView noDataMembers;
private View.OnClickListener onClickListener;
private TeamMembersByOrgAdapter adapter;
private GridView mGridView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_org_team_members);
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
TextView toolbarTitle = findViewById(R.id.toolbar_title);
noDataMembers = findViewById(R.id.noDataMembers);
mGridView = findViewById(R.id.gridView);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(getIntent().getStringExtra("teamTitle") != null && !getIntent().getStringExtra("teamTitle").equals("")) {
toolbarTitle.setText(getIntent().getStringExtra("teamTitle"));
}
else {
toolbarTitle.setText(R.string.orgTeamMembers);
}
String teamId;
if(getIntent().getStringExtra("teamId") != null && !getIntent().getStringExtra("teamId").equals("")){
teamId = getIntent().getStringExtra("teamId");
}
else {
teamId = "0";
}
getIntent().getStringExtra("teamId");
//Log.i("teamId", getIntent().getStringExtra("teamId"));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), Integer.valueOf(teamId));
}
private void fetchDataAsync(String instanceUrl, String instanceToken, int teamId) {
TeamMembersByOrgViewModel teamMembersModel = new ViewModelProvider(this).get(TeamMembersByOrgViewModel.class);
teamMembersModel.getMembersByOrgList(instanceUrl, instanceToken, teamId, getApplicationContext()).observe(this, new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> teamMembersListMain) {
adapter = new TeamMembersByOrgAdapter(getApplicationContext(), teamMembersListMain);
if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter);
noDataMembers.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mGridView.setAdapter(adapter);
noDataMembers.setVisibility(View.VISIBLE);
}
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}

View File

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

View File

@ -1,74 +1,64 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.util.Patterns; import android.util.Patterns;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.AddEmail; import org.mian.gitnex.models.AddEmail;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class ProfileEmailActivity extends BaseActivity { public class ProfileEmailActivity extends AppCompatActivity {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private EditText userEmail; private EditText userEmail;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
private Button addEmailButton; private Button addEmailButton;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_profile_email;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_profile_email);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = findViewById(R.id.close);
userEmail = findViewById(R.id.userEmail); userEmail = findViewById(R.id.userEmail);
addEmailButton = findViewById(R.id.addEmailButton); addEmailButton = findViewById(R.id.addEmailButton);
userEmail.requestFocus();
assert imm != null;
imm.showSoftInput(userEmail, InputMethodManager.SHOW_IMPLICIT);
initCloseListener(); initCloseListener();
closeActivity.setOnClickListener(onClickListener); closeActivity.setOnClickListener(onClickListener);
if(!connToInternet) { if(!connToInternet) {
disableProcessButton(); disableProcessButton();
} else { } else {
addEmailButton.setOnClickListener(addEmailListener); addEmailButton.setOnClickListener(addEmailListener);
} }
} }
@ -81,8 +71,8 @@ public class ProfileEmailActivity extends BaseActivity {
private void processAddNewEmail() { private void processAddNewEmail() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
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");
@ -91,20 +81,20 @@ public class ProfileEmailActivity extends BaseActivity {
if(!connToInternet) { if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return; return;
} }
if(newUserEmail.equals("")) { if(newUserEmail.equals("")) {
Toasty.error(ctx, getString(R.string.emailErrorEmpty)); Toasty.info(getApplicationContext(), getString(R.string.emailErrorEmpty));
return; return;
} }
else if(!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) { else if(!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) {
Toasty.warning(ctx, getString(R.string.emailErrorInvalid)); Toasty.info(getApplicationContext(), getString(R.string.emailErrorInvalid));
return; return;
} }
@ -112,19 +102,19 @@ public class ProfileEmailActivity extends BaseActivity {
List<String> newEmailList = new ArrayList<>(Arrays.asList(newUserEmail.split(","))); List<String> newEmailList = new ArrayList<>(Arrays.asList(newUserEmail.split(",")));
disableProcessButton(); disableProcessButton();
addNewEmail(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), newEmailList); addNewEmail(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), newEmailList);
} }
private void addNewEmail(final String instanceUrl, final String token, List<String> newUserEmail) { private void addNewEmail(final String instanceUrl, final String token, List<String> newUserEmail) {
AddEmail addEmailFunc = new AddEmail(newUserEmail); AddEmail addEmailFunc = new AddEmail(newUserEmail);
final TinyDB tinyDb = new TinyDB(appCtx); final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<JsonElement> call; Call<JsonElement> call;
call = RetrofitClient call = RetrofitClient
.getInstance(instanceUrl, ctx) .getInstance(instanceUrl, getApplicationContext())
.getApiInterface() .getApiInterface()
.addNewEmail(token, addEmailFunc); .addNewEmail(token, addEmailFunc);
@ -135,7 +125,7 @@ public class ProfileEmailActivity extends BaseActivity {
if(response.code() == 201) { if(response.code() == 201) {
Toasty.success(ctx, getString(R.string.emailAddedText)); Toasty.info(getApplicationContext(), getString(R.string.emailAddedText));
tinyDb.putBoolean("emailsRefresh", true); tinyDb.putBoolean("emailsRefresh", true);
enableProcessButton(); enableProcessButton();
finish(); finish();
@ -153,25 +143,25 @@ public class ProfileEmailActivity extends BaseActivity {
else if(response.code() == 403) { else if(response.code() == 403) {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); Toasty.info(ctx, ctx.getString(R.string.authorizeError));
} }
else if(response.code() == 404) { else if(response.code() == 404) {
enableProcessButton(); enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)); Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
} }
else if(response.code() == 422) { else if(response.code() == 422) {
enableProcessButton(); enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.emailErrorInUse)); Toasty.info(ctx, ctx.getString(R.string.emailErrorInUse));
} }
else { else {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, getString(R.string.labelGeneralError)); Toasty.info(getApplicationContext(), getString(R.string.labelGeneralError));
} }
@ -187,18 +177,32 @@ public class ProfileEmailActivity extends BaseActivity {
} }
private void initCloseListener() { private void initCloseListener() {
onClickListener = new View.OnClickListener() {
onClickListener = view -> finish(); @Override
public void onClick(View view) {
finish();
}
};
} }
private void disableProcessButton() { private void disableProcessButton() {
addEmailButton.setEnabled(false); addEmailButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
addEmailButton.setBackground(shape);
} }
private void enableProcessButton() { private void enableProcessButton() {
addEmailButton.setEnabled(true); addEmailButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
addEmailButton.setBackground(shape);
} }
} }

View File

@ -1,426 +1,280 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.graphics.drawable.GradientDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log; import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import com.hendraanggrian.appcompat.socialview.Mention; import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter; import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView; import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.actions.IssueActions; import org.mian.gitnex.actions.IssueActions;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators; import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues; import org.mian.gitnex.models.Issues;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.List; import java.util.List;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class ReplyToIssueActivity extends BaseActivity { public class ReplyToIssueActivity extends AppCompatActivity {
public ImageView closeActivity; public ImageView closeActivity;
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
final Context ctx = this; final Context ctx = this;
private Context appCtx;
private TextView draftSaved; private SocialAutoCompleteTextView addComment;
private SocialAutoCompleteTextView addComment; private ArrayAdapter<Mention> defaultMentionAdapter;
private ArrayAdapter<Mention> defaultMentionAdapter; private Button replyButton;
private Button replyButton;
private String TAG = StaticGlobalVariables.replyToIssueActivity;
private long draftIdOnCreate;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_reply_to_issue;
}
@Override super.onCreate(savedInstanceState);
public void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_reply_to_issue);
super.onCreate(savedInstanceState); boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
appCtx = getApplicationContext(); TinyDB tinyDb = new TinyDB(getApplicationContext());
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); addComment = findViewById(R.id.addComment);
addComment.setShowSoftInputOnFocus(true);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); defaultMentionAdapter = new MentionArrayAdapter<>(this);
TinyDB tinyDb = new TinyDB(appCtx); loadCollaboratorsList();
draftSaved = findViewById(R.id.draftSaved); addComment.setMentionAdapter(defaultMentionAdapter);
addComment = findViewById(R.id.addComment);
addComment.setShowSoftInputOnFocus(true);
defaultMentionAdapter = new MentionArrayAdapter<>(ctx); closeActivity = findViewById(R.id.close);
loadCollaboratorsList(); TextView toolbar_title = findViewById(R.id.toolbar_title);
addComment.setMentionAdapter(defaultMentionAdapter); if(!tinyDb.getString("issueTitle").isEmpty()) {
toolbar_title.setText(tinyDb.getString("issueTitle"));
}
closeActivity = findViewById(R.id.close); initCloseListener();
TextView toolbar_title = findViewById(R.id.toolbar_title); closeActivity.setOnClickListener(onClickListener);
addComment.requestFocus(); replyButton = findViewById(R.id.replyButton);
assert imm != null;
imm.showSoftInput(addComment, InputMethodManager.SHOW_IMPLICIT);
if(!tinyDb.getString("issueTitle").isEmpty()) { if(getIntent().getStringExtra("commentAction") != null && getIntent().getStringExtra("commentAction").equals("edit")) {
toolbar_title.setText(tinyDb.getString("issueTitle"));
}
initCloseListener(); addComment.setText(getIntent().getStringExtra("commentBody"));
closeActivity.setOnClickListener(onClickListener); final String commentId = getIntent().getStringExtra("commentId");
if(getIntent().getStringExtra("draftId") != null) { toolbar_title.setText(getResources().getString(R.string.editCommentTitle));
replyButton.setText(getResources().getString(R.string.editCommentButtonText));
draftIdOnCreate = Long.parseLong(Objects.requireNonNull(getIntent().getStringExtra("draftId"))); replyButton.setOnClickListener(new View.OnClickListener() {
} public void onClick(View v) {
else { disableProcessButton();
IssueActions.editIssueComment(ctx, Integer.valueOf(commentId), addComment.getText().toString());
}
draftIdOnCreate = returnDraftId(); });
}
replyButton = findViewById(R.id.replyButton); return;
if(getIntent().getStringExtra("commentBody") != null) { }
addComment.setText(getIntent().getStringExtra("commentBody")); if(!connToInternet) {
if(getIntent().getBooleanExtra("cursorToEnd", false)) { disableProcessButton();
addComment.setSelection(addComment.length());
}
} } else {
if(getIntent().getStringExtra("draftTitle") != null) { replyButton.setOnClickListener(replyToIssue);
toolbar_title.setText(getIntent().getStringExtra("draftTitle")); }
} }
if(getIntent().getStringExtra("commentAction") != null && Objects.equals(getIntent().getStringExtra("commentAction"), "edit") && !Objects.equals(getIntent().getStringExtra("commentId"), "new")) { public void loadCollaboratorsList() {
final String commentId = getIntent().getStringExtra("commentId"); final TinyDB tinyDb = new TinyDB(getApplicationContext());
toolbar_title.setText(getResources().getString(R.string.editCommentTitle)); final String instanceUrl = tinyDb.getString("instanceUrl");
replyButton.setText(getResources().getString(R.string.editCommentButtonText)); final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
addComment.addTextChangedListener(new TextWatcher() { Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
public void afterTextChanged(Editable s) { call.enqueue(new Callback<List<Collaborators>>() {
} @Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
public void beforeTextChanged(CharSequence s, int start, int count, int after) { if (response.isSuccessful()) {
} assert response.body() != null;
String fullName = "";
for (int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(
new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
public void onTextChanged(CharSequence s, int start, int before, int count) { } else {
saveDraft(addComment.getText().toString(), commentId, draftIdOnCreate); Log.i("onResponse", String.valueOf(response.code()));
draftSaved.setVisibility(View.VISIBLE);
} }
}); }
replyButton.setOnClickListener(v -> { @Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.getMessage());
}
disableProcessButton(); });
assert commentId != null; }
IssueActions.editIssueComment(ctx, Integer.parseInt(commentId), addComment.getText().toString(), draftIdOnCreate);
}); private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
return; private View.OnClickListener replyToIssue = new View.OnClickListener() {
public void onClick(View v) {
processNewCommentReply();
}
};
} private void processNewCommentReply() {
addComment.addTextChangedListener(new TextWatcher() { String newReplyDT = addComment.getText().toString();
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
public void afterTextChanged(Editable s) { if(!connToInternet) {
} Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
} if(newReplyDT.equals("")) {
public void onTextChanged(CharSequence s, int start, int before, int count) { Toasty.info(getApplicationContext(), getString(R.string.commentEmptyError));
saveDraft(addComment.getText().toString(), "new", draftIdOnCreate); }
draftSaved.setVisibility(View.VISIBLE); else {
} disableProcessButton();
replyComment(newReplyDT);
}); }
if(!connToInternet) { }
disableProcessButton(); private void replyComment(String newReplyDT) {
} final TinyDB tinyDb = new TinyDB(getApplicationContext());
else {
replyButton.setOnClickListener(replyToIssue); final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
} Issues issueComment = new Issues(newReplyDT);
} Call<Issues> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.replyCommentToIssue(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, issueComment);
private void saveDraft(String draftText, String commentId, long draftIdOnCreate) { call.enqueue(new Callback<Issues>() {
TinyDB tinyDb = new TinyDB(getApplicationContext()); @Override
public void onResponse(@NonNull Call<Issues> call, @NonNull retrofit2.Response<Issues> response) {
int repositoryId = (int) tinyDb.getLong("repositoryId", 0); if(response.code() == 201) {
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
int issueNumber = Integer.parseInt(tinyDb.getString("issueNumber"));
DraftsApi draftsApi = new DraftsApi(appCtx); Toasty.info(getApplicationContext(), getString(R.string.commentSuccess));
tinyDb.putBoolean("commentPosted", true);
tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("resumePullRequests", true);
finish();
if(draftIdOnCreate == 0) { }
else if(response.code() == 401) {
draftsApi.insertDraft(repositoryId, currentActiveAccountId, issueNumber, draftText, StaticGlobalVariables.draftTypeComment, commentId); enableProcessButton();
} AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
else { getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
DraftsApi.updateDraft(draftText, (int) draftIdOnCreate, commentId); //updateDraftByIssueIdAsyncTask(draftText, issueNumber, repositoryId, commentId); }
} else {
} enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.commentError));
private long returnDraftId() { }
TinyDB tinyDb = new TinyDB(getApplicationContext()); }
int repositoryId = (int) tinyDb.getLong("repositoryId", 0); @Override
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId"); public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
int issueNumber = Integer.parseInt(tinyDb.getString("issueNumber")); Log.e("onFailure", t.toString());
enableProcessButton();
}
});
DraftsApi draftsApi = new DraftsApi(appCtx); }
return draftsApi.insertDraft(repositoryId, currentActiveAccountId, issueNumber, "", StaticGlobalVariables.draftTypeComment, ""); private void disableProcessButton() {
} replyButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
replyButton.setBackground(shape);
public void loadCollaboratorsList() { }
final TinyDB tinyDb = new TinyDB(appCtx); private void enableProcessButton() {
final String instanceUrl = tinyDb.getString("instanceUrl"); replyButton.setEnabled(true);
final String loginUid = tinyDb.getString("loginUid"); GradientDrawable shape = new GradientDrawable();
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); shape.setCornerRadius( 8 );
String repoFullName = tinyDb.getString("repoFullName"); shape.setColor(getResources().getColor(R.color.btnBackground));
String[] parts = repoFullName.split("/"); replyButton.setBackground(shape);
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient }
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
String fullName = "";
for(int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
}
else {
Log.i(TAG, String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private View.OnClickListener replyToIssue = v -> processNewCommentReply();
private void processNewCommentReply() {
String newReplyDT = addComment.getText().toString();
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
if(!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newReplyDT.equals("")) {
Toasty.error(ctx, getString(R.string.commentEmptyError));
}
else {
disableProcessButton();
replyComment(newReplyDT);
}
}
private void replyComment(String newReplyDT) {
final TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
Issues issueComment = new Issues(newReplyDT);
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.replyCommentToIssue(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueComment);
call.enqueue(new Callback<Issues>() {
@Override
public void onResponse(@NonNull Call<Issues> call, @NonNull retrofit2.Response<Issues> response) {
if(response.code() == 201) {
Toasty.success(ctx, getString(R.string.commentSuccess));
tinyDb.putBoolean("commentPosted", true);
tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("resumePullRequests", true);
// delete draft comment
if(tinyDb.getBoolean("draftsCommentsDeletionEnabled")) {
DraftsApi draftsApi = new DraftsApi(appCtx);
draftsApi.deleteSingleDraft((int) draftIdOnCreate);
}
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.commentError));
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
enableProcessButton();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.reply_to_issue, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.replyToIssueMenu:
Intent fragmentIntent = new Intent(ReplyToIssueActivity.this, MainActivity.class);
fragmentIntent.putExtra("launchFragment", "drafts");
ReplyToIssueActivity.this.startActivity(fragmentIntent);
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
private void disableProcessButton() {
replyButton.setEnabled(false);
}
private void enableProcessButton() {
replyButton.setEnabled(true);
}
} }

View File

@ -1,14 +1,19 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import com.google.android.material.tabs.TabLayout;
import com.google.gson.JsonElement;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import retrofit2.Call;
import retrofit2.Callback;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -16,24 +21,11 @@ import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import com.google.gson.JsonElement;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BottomSheetIssuesFilterFragment;
import org.mian.gitnex.fragments.BottomSheetMilestonesFilterFragment;
import org.mian.gitnex.fragments.BottomSheetPullRequestFilterFragment;
import org.mian.gitnex.fragments.BottomSheetRepoFragment;
import org.mian.gitnex.fragments.BranchesFragment; import org.mian.gitnex.fragments.BranchesFragment;
import org.mian.gitnex.fragments.ClosedIssuesFragment;
import org.mian.gitnex.fragments.CollaboratorsFragment; import org.mian.gitnex.fragments.CollaboratorsFragment;
import org.mian.gitnex.fragments.FilesFragment; import org.mian.gitnex.fragments.FilesFragment;
import org.mian.gitnex.fragments.IssuesFragment; import org.mian.gitnex.fragments.IssuesFragment;
@ -41,620 +33,310 @@ import org.mian.gitnex.fragments.LabelsFragment;
import org.mian.gitnex.fragments.MilestonesFragment; import org.mian.gitnex.fragments.MilestonesFragment;
import org.mian.gitnex.fragments.PullRequestsFragment; import org.mian.gitnex.fragments.PullRequestsFragment;
import org.mian.gitnex.fragments.ReleasesFragment; import org.mian.gitnex.fragments.ReleasesFragment;
import org.mian.gitnex.fragments.RepoBottomSheetFragment;
import org.mian.gitnex.fragments.RepoInfoFragment; import org.mian.gitnex.fragments.RepoInfoFragment;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.UserRepositories; import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo; import org.mian.gitnex.models.WatchRepository;
import java.util.ArrayList; import org.mian.gitnex.util.AppUtil;
import java.util.List; import org.mian.gitnex.util.TinyDB;
import java.util.Objects; import java.util.Objects;
import retrofit2.Call; import android.net.Uri;
import retrofit2.Callback;
import retrofit2.Response;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoFragment.BottomSheetListener, BottomSheetIssuesFilterFragment.BottomSheetListener, public class RepoDetailActivity extends AppCompatActivity implements RepoBottomSheetFragment.BottomSheetListener {
BottomSheetPullRequestFilterFragment.BottomSheetListener, BottomSheetMilestonesFilterFragment.BottomSheetListener {
private TextView textViewBadge;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_repo_detail);
TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
String repoName1 = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String repoOwner = parts[0];
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String appLocale = tinyDb.getString("locale");
AppUtil.setAppLocale(getResources(), appLocale);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repoName1);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
ViewPager mViewPager = findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = findViewById(R.id.tabs);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
if(tinyDb.getBoolean("enableCounterIssueBadge")) {
@SuppressLint("InflateParams") View tabHeader = LayoutInflater.from(this).inflate(R.layout.badge, null);
textViewBadge = tabHeader.findViewById(R.id.counterBadge);
if(!tinyDb.getString("issuesCounter").isEmpty()) {
getRepoInfo(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName1);
}
Objects.requireNonNull(tabLayout.getTabAt(2)).setCustomView(tabHeader);
TabLayout.Tab tabOpenIssues = tabLayout.getTabAt(2);
ColorStateList textColor = tabLayout.getTabTextColors();
assert tabOpenIssues != null;
TextView openIssueTabView = Objects.requireNonNull(tabOpenIssues.getCustomView()).findViewById(R.id.counterBadgeText);
openIssueTabView.setTextColor(textColor);
}
checkRepositoryStarStatus(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName1);
checkRepositoryWatchStatus(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName1);
}
@Override
public void onResume() {
super.onResume();
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getBoolean("enableCounterIssueBadge")) {
getRepoInfo(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.repo_dotted_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
finish();
return true;
case R.id.repoMenu:
RepoBottomSheetFragment bottomSheet = new RepoBottomSheetFragment();
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onButtonClicked(String text) {
switch (text) {
case "label":
startActivity(new Intent(RepoDetailActivity.this, CreateLabelActivity.class));
break;
case "newIssue":
startActivity(new Intent(RepoDetailActivity.this, CreateIssueActivity.class));
break;
case "newMilestone":
startActivity(new Intent(RepoDetailActivity.this, NewMilestoneActivity.class));
break;
case "addCollaborator":
startActivity(new Intent(RepoDetailActivity.this, AddCollaboratorToRepositoryActivity.class));
break;
case "createRelease":
startActivity(new Intent(RepoDetailActivity.this, CreateReleaseActivity.class));
break;
case "openWebRepo":
TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
String instanceUrlWithProtocol = "https://" + tinyDb.getString("instanceUrlRaw");
if(!tinyDb.getString("instanceUrlWithProtocol").isEmpty()) {
instanceUrlWithProtocol = tinyDb.getString("instanceUrlWithProtocol");
}
Uri url = Uri.parse(instanceUrlWithProtocol + "/" + repoFullName);
Intent i = new Intent(Intent.ACTION_VIEW, url);
startActivity(i);
break;
case "newFile":
startActivity(new Intent(RepoDetailActivity.this, NewFileActivity.class));
break;
}
}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
SectionsPagerAdapter(FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
@NonNull
@Override
public Fragment getItem(int position) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
Fragment fragment = null;
switch (position) {
case 0: // information
return RepoInfoFragment.newInstance(repoOwner, repoName);
case 1: // files
return FilesFragment.newInstance(repoOwner, repoName);
case 2: // issues
fragment = new IssuesFragment();
break;
case 3: // closed issues
fragment = new ClosedIssuesFragment();
break;
case 4: // pull requests
fragment = new PullRequestsFragment();
break;
case 5: // milestones
return MilestonesFragment.newInstance(repoOwner, repoName);
case 6: // labels
return LabelsFragment.newInstance(repoOwner, repoName);
case 7: // branches
return BranchesFragment.newInstance(repoOwner, repoName);
case 8: // releases
return ReleasesFragment.newInstance(repoOwner, repoName);
case 9: // collaborators
return CollaboratorsFragment.newInstance(repoOwner, repoName);
}
return fragment;
}
@Override
public int getCount() {
return 10;
}
}
private void getRepoInfo(String instanceUrl, String token, final String owner, String repo) {
Call<UserRepositories> call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getUserRepository(token, owner, repo);
call.enqueue(new Callback<UserRepositories>() {
@Override
public void onResponse(@NonNull Call<UserRepositories> call, @NonNull retrofit2.Response<UserRepositories> response) {
UserRepositories repoInfo = response.body();
if (response.isSuccessful()) {
if (response.code() == 200) {
assert repoInfo != null;
textViewBadge.setText(repoInfo.getOpen_issues_count());
}
}
else {
Log.e("onFailure", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private TextView textViewBadgeIssue; private void checkRepositoryStarStatus(String instanceUrl, String instanceToken, final String owner, String repo) {
private TextView textViewBadgePull;
private TextView textViewBadgeRelease;
private FragmentRefreshListener fragmentRefreshListener; Call<JsonElement> call;
private FragmentRefreshListenerPr fragmentRefreshListenerPr;
private FragmentRefreshListenerMilestone fragmentRefreshListenerMilestone;
private FragmentRefreshListenerFiles fragmentRefreshListenerFiles;
private final Context ctx = this; call = RetrofitClient
private Context appCtx; .getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.checkRepoStarStatus(instanceToken, owner, repo);
private TinyDB tinyDB; call.enqueue(new Callback<JsonElement>() {
private String instanceUrl; @Override
private String loginUid; public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
private String instanceToken;
private String repositoryOwner; TinyDB tinyDb = new TinyDB(getApplicationContext());
private String repositoryName; tinyDb.putInt("repositoryStarStatus", response.code());
public static ViewPager mViewPager; }
private int tabsCount;
@Override @Override
protected int getLayoutResourceId() { public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
return R.layout.activity_repo_detail; }
}
@Override private void checkRepositoryWatchStatus(String instanceUrl, String instanceToken, final String owner, String repo) {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); Call<WatchRepository> call;
appCtx = getApplicationContext();
tinyDB = new TinyDB(appCtx); call = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.checkRepoWatchStatus(instanceToken, owner, repo);
String[] repoNameParts = tinyDB.getString("repoFullName").split("/"); call.enqueue(new Callback<WatchRepository>() {
repositoryOwner = repoNameParts[0];
repositoryName = repoNameParts[1];
Toolbar toolbar = findViewById(R.id.toolbar); @Override
public void onResponse(@NonNull Call<WatchRepository> call, @NonNull retrofit2.Response<WatchRepository> response) {
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title); TinyDB tinyDb = new TinyDB(getApplicationContext());
toolbarTitle.setText(repositoryName);
setSupportActionBar(toolbar); if(response.code() == 200) {
Objects.requireNonNull(getSupportActionBar()).setTitle(repositoryName); assert response.body() != null;
getSupportActionBar().setDisplayHomeAsUpEnabled(true); if(response.body().getSubscribed()) {
tinyDb.putBoolean("repositoryWatchStatus", true);
}
}
else {
tinyDb.putBoolean("repositoryWatchStatus", false);
}
instanceUrl = tinyDB.getString("instanceUrl"); }
loginUid = tinyDB.getString("loginUid");
instanceToken = "token " + tinyDB.getString(loginUid + "-token");
tinyDB.putString("repoIssuesState", "open"); @Override
tinyDB.putString("repoPrState", "open"); public void onFailure(@NonNull Call<WatchRepository> call, @NonNull Throwable t) {
tinyDB.putString("milestoneState", "open"); Log.e("onFailure", t.toString());
}
});
Typeface myTypeface; }
switch(tinyDB.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
break;
}
toolbarTitle.setTypeface(myTypeface);
TabLayout tabLayout = findViewById(R.id.tabs);
ViewGroup viewGroup = (ViewGroup) tabLayout.getChildAt(0);
tabsCount = viewGroup.getChildCount();
for(int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) viewGroup.getChildAt(j);
int tabChildCount = vgTab.getChildCount();
for(int i = 0; i < tabChildCount; i++) {
View tabViewChild = vgTab.getChildAt(i);
if(tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(myTypeface);
}
}
}
// Only show collaborators tab, if you have permission to
View collaboratorTab = viewGroup.getChildAt(8);
if(tinyDB.getBoolean("isRepoAdmin") || new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
collaboratorTab.setVisibility(View.VISIBLE);
}
else {
tabsCount--;
collaboratorTab.setVisibility(View.GONE);
}
mViewPager = findViewById(R.id.container);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
if(tinyDB.getBoolean("enableCounterBadges")) {
@SuppressLint("InflateParams") View tabHeader2 = LayoutInflater.from(this).inflate(R.layout.badge_issue, null);
textViewBadgeIssue = tabHeader2.findViewById(R.id.counterBadgeIssue);
@SuppressLint("InflateParams") View tabHeader4 = LayoutInflater.from(this).inflate(R.layout.badge_pull, null);
textViewBadgePull = tabHeader4.findViewById(R.id.counterBadgePull);
@SuppressLint("InflateParams") View tabHeader6 = LayoutInflater.from(this).inflate(R.layout.badge_release, null);
textViewBadgeRelease = tabHeader6.findViewById(R.id.counterBadgeRelease);
textViewBadgeIssue.setVisibility(View.GONE);
textViewBadgePull.setVisibility(View.GONE);
textViewBadgeRelease.setVisibility(View.GONE);
getRepoInfo(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
ColorStateList textColor = tabLayout.getTabTextColors();
// Issue count
if(textViewBadgeIssue.getText() != "") {
TabLayout.Tab tabOpenIssues = tabLayout.getTabAt(2);
Objects.requireNonNull(tabLayout.getTabAt(2)).setCustomView(tabHeader2);
assert tabOpenIssues != null; // FIXME This should be cleaned up
TextView openIssueTabView = Objects.requireNonNull(tabOpenIssues.getCustomView()).findViewById(R.id.counterBadgeIssueText);
openIssueTabView.setTextColor(textColor);
}
// Pull request count
if(textViewBadgePull.getText() != "") { // only show if API returned a number
Objects.requireNonNull(tabLayout.getTabAt(3)).setCustomView(tabHeader4);
TabLayout.Tab tabOpenPulls = tabLayout.getTabAt(3);
assert tabOpenPulls != null; // FIXME This should be cleaned up
TextView openPullTabView = Objects.requireNonNull(tabOpenPulls.getCustomView()).findViewById(R.id.counterBadgePullText);
openPullTabView.setTextColor(textColor);
}
// Release count
if(new Version("1.11.4").less(tinyDB.getString("giteaVersion"))) {
if(textViewBadgeRelease.getText() != "") { // only show if API returned a number
Objects.requireNonNull(tabLayout.getTabAt(5)).setCustomView(tabHeader6);
TabLayout.Tab tabOpenRelease = tabLayout.getTabAt(5);
assert tabOpenRelease != null; // FIXME This should be cleaned up
TextView openReleaseTabView = Objects.requireNonNull(tabOpenRelease.getCustomView()).findViewById(R.id.counterBadgeReleaseText);
openReleaseTabView.setTextColor(textColor);
}
}
}
checkRepositoryStarStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
checkRepositoryWatchStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
}
@Override
public void onResume() {
super.onResume();
if(tinyDB.getBoolean("enableCounterIssueBadge")) {
getRepoInfo(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.repo_dotted_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch(id) {
case android.R.id.home:
finish();
return true;
case R.id.repoMenu:
BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment();
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
return true;
case R.id.filter:
BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment();
filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet");
return true;
case R.id.filterPr:
BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment();
filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet");
return true;
case R.id.filterMilestone:
BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment();
filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet");
return true;
case R.id.switchBranches:
chooseBranch();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onButtonClicked(String text) {
switch(text) {
case "label":
startActivity(new Intent(RepoDetailActivity.this, CreateLabelActivity.class));
break;
case "newIssue":
startActivity(new Intent(RepoDetailActivity.this, CreateIssueActivity.class));
break;
case "newMilestone":
startActivity(new Intent(RepoDetailActivity.this, CreateMilestoneActivity.class));
break;
case "addCollaborator":
startActivity(new Intent(RepoDetailActivity.this, AddCollaboratorToRepositoryActivity.class));
break;
case "chooseBranch":
chooseBranch();
break;
case "createRelease":
startActivity(new Intent(RepoDetailActivity.this, CreateReleaseActivity.class));
break;
case "openWebRepo":
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(tinyDB.getString("repoHtmlUrl")));
startActivity(i);
break;
case "shareRepo":
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, tinyDB.getString("repoHtmlUrl"));
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, tinyDB.getString("repoHtmlUrl"));
startActivity(Intent.createChooser(sharingIntent, tinyDB.getString("repoHtmlUrl")));
break;
case "copyRepoUrl":
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("repoUrl", tinyDB.getString("repoHtmlUrl"));
assert clipboard != null;
clipboard.setPrimaryClip(clip);
Toasty.info(ctx, ctx.getString(R.string.copyIssueUrlToastMsg));
break;
case "newFile":
startActivity(new Intent(RepoDetailActivity.this, CreateFileActivity.class));
break;
case "openIssues":
if(getFragmentRefreshListener() != null) {
getFragmentRefreshListener().onRefresh("open");
}
break;
case "closedIssues":
if(getFragmentRefreshListener() != null) {
getFragmentRefreshListener().onRefresh("closed");
}
break;
case "openPr":
if(getFragmentRefreshListenerPr() != null) {
getFragmentRefreshListenerPr().onRefresh("open");
}
break;
case "closedPr":
if(getFragmentRefreshListenerPr() != null) {
getFragmentRefreshListenerPr().onRefresh("closed");
}
break;
case "openMilestone":
if(getFragmentRefreshListenerMilestone() != null) {
getFragmentRefreshListenerMilestone().onRefresh("open");
}
break;
case "closedMilestone":
if(getFragmentRefreshListenerMilestone() != null) {
getFragmentRefreshListenerMilestone().onRefresh("closed");
}
break;
}
}
private void chooseBranch() {
Call<List<Branches>> call = RetrofitClient.getInstance(instanceUrl, ctx)
.getApiInterface()
.getBranches(instanceToken, repositoryOwner, repositoryName);
call.enqueue(new Callback<List<Branches>>() {
@Override
public void onResponse(@NonNull Call<List<Branches>> call, @NonNull Response<List<Branches>> response) {
if(response.code() == 200) {
List<String> branchesList = new ArrayList<>();
int selectedBranch = 0;
assert response.body() != null;
for(int i = 0; i < response.body().size(); i++) {
Branches branches = response.body().get(i);
branchesList.add(branches.getName());
if(tinyDB.getString("repoBranch").equals(branches.getName())) {
selectedBranch = i;
}
}
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx);
pBuilder.setTitle(R.string.pageTitleChooseBranch);
pBuilder.setSingleChoiceItems(branchesList.toArray(new String[0]), selectedBranch, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
tinyDB.putString("repoBranch", branchesList.get(i));
if(getFragmentRefreshListenerFiles() != null) {
getFragmentRefreshListenerFiles().onRefresh(branchesList.get(i));
}
dialogInterface.dismiss();
}
});
pBuilder.setNeutralButton(R.string.cancelButton, null);
pBuilder.create().show();
}
}
@Override
public void onFailure(@NonNull Call<List<Branches>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
SectionsPagerAdapter(FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
@NonNull
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch(position) {
case 0: // Repository details
return RepoInfoFragment.newInstance(repositoryOwner, repositoryName);
case 1: // Files
return FilesFragment.newInstance(repositoryOwner, repositoryName, tinyDB.getString("repoBranch"));
case 2: // Issues
fragment = new IssuesFragment();
break;
case 3: // Pull requests
fragment = new PullRequestsFragment();
break;
case 4: // Branches
return BranchesFragment.newInstance(repositoryOwner, repositoryName);
case 5: // Releases
return ReleasesFragment.newInstance(repositoryOwner, repositoryName);
case 6: // Milestones
fragment = new MilestonesFragment();
break;
case 7: // Labels
return LabelsFragment.newInstance(repositoryOwner, repositoryName);
case 8: // Collaborators
return CollaboratorsFragment.newInstance(repositoryOwner, repositoryName);
}
assert fragment != null;
return fragment;
}
@Override
public int getCount() {
return tabsCount;
}
}
private void getRepoInfo(String instanceUrl, String token, final String owner, String repo) {
Call<UserRepositories> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserRepository(token, owner, repo);
call.enqueue(new Callback<UserRepositories>() {
@Override
public void onResponse(@NonNull Call<UserRepositories> call, @NonNull retrofit2.Response<UserRepositories> response) {
UserRepositories repoInfo = response.body();
if(response.code() == 200) {
if(tinyDB.getBoolean("enableCounterBadges")) {
assert repoInfo != null;
if(repoInfo.getOpen_issues_count() != null) {
textViewBadgeIssue.setVisibility(View.VISIBLE);
textViewBadgeIssue.setText(repoInfo.getOpen_issues_count());
}
if(repoInfo.getOpen_pull_count() != null) {
textViewBadgePull.setVisibility(View.VISIBLE);
textViewBadgePull.setText(repoInfo.getOpen_pull_count());
}
if(repoInfo.getRelease_count() != null) {
textViewBadgeRelease.setVisibility(View.VISIBLE);
textViewBadgeRelease.setText(repoInfo.getRelease_count());
}
}
}
else {
Log.e("onFailure", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void checkRepositoryStarStatus(String instanceUrl, String instanceToken, final String owner, String repo) {
Call<JsonElement> call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkRepoStarStatus(instanceToken, owner, repo);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
tinyDB.putInt("repositoryStarStatus", response.code());
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void checkRepositoryWatchStatus(String instanceUrl, String instanceToken, final String owner, String repo) {
Call<WatchInfo> call;
call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkRepoWatchStatus(instanceToken, owner, repo);
call.enqueue(new Callback<WatchInfo>() {
@Override
public void onResponse(@NonNull Call<WatchInfo> call, @NonNull retrofit2.Response<WatchInfo> response) {
if(response.code() == 200) {
assert response.body() != null;
if(response.body().getSubscribed()) {
tinyDB.putBoolean("repositoryWatchStatus", true);
}
}
else {
tinyDB.putBoolean("repositoryWatchStatus", false);
}
}
@Override
public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
// Issues interface
public FragmentRefreshListener getFragmentRefreshListener() { return fragmentRefreshListener; }
public void setFragmentRefreshListener(FragmentRefreshListener fragmentRefreshListener) { this.fragmentRefreshListener = fragmentRefreshListener; }
public interface FragmentRefreshListener { void onRefresh(String text); }
// Pull request interface
public FragmentRefreshListenerPr getFragmentRefreshListenerPr() { return fragmentRefreshListenerPr; }
public void setFragmentRefreshListenerPr(FragmentRefreshListenerPr fragmentRefreshListenerPr) { this.fragmentRefreshListenerPr = fragmentRefreshListenerPr; }
public interface FragmentRefreshListenerPr { void onRefresh(String text); }
// Milestones interface
public FragmentRefreshListenerMilestone getFragmentRefreshListenerMilestone() { return fragmentRefreshListenerMilestone; }
public void setFragmentRefreshListenerMilestone(FragmentRefreshListenerMilestone fragmentRefreshListenerMilestone) { this.fragmentRefreshListenerMilestone = fragmentRefreshListenerMilestone; }
public interface FragmentRefreshListenerMilestone { void onRefresh(String text); }
// Files interface
public FragmentRefreshListenerFiles getFragmentRefreshListenerFiles() { return fragmentRefreshListenerFiles; }
public void setFragmentRefreshListenerFiles(FragmentRefreshListenerFiles fragmentRefreshListenerFiles) { this.fragmentRefreshListenerFiles = fragmentRefreshListenerFiles; }
public interface FragmentRefreshListenerFiles { void onRefresh(String text); }
} }

View File

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

View File

@ -1,20 +1,20 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.view.View; import android.view.View;
import android.widget.GridView; import android.widget.GridView;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoStargazersAdapter; import org.mian.gitnex.adapters.RepoStargazersAdapter;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo; import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.RepoStargazersViewModel; import org.mian.gitnex.viewmodels.RepoStargazersViewModel;
import java.util.List; import java.util.List;
@ -22,7 +22,7 @@ import java.util.List;
* Author M M Arif * Author M M Arif
*/ */
public class RepoStargazersActivity extends BaseActivity { public class RepoStargazersActivity extends AppCompatActivity {
private TextView noDataStargazers; private TextView noDataStargazers;
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
@ -30,21 +30,12 @@ public class RepoStargazersActivity extends BaseActivity {
private GridView mGridView; private GridView mGridView;
private ProgressBar mProgressBar; private ProgressBar mProgressBar;
final Context ctx = this;
private Context appCtx;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_repo_stargazers;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_repo_stargazers);
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
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");
@ -65,7 +56,7 @@ public class RepoStargazersActivity extends BaseActivity {
toolbarTitle.setText(R.string.repoStargazersInMenu); toolbarTitle.setText(R.string.repoStargazersInMenu);
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName); fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
} }
@ -73,10 +64,10 @@ public class RepoStargazersActivity extends BaseActivity {
RepoStargazersViewModel repoStargazersModel = new ViewModelProvider(this).get(RepoStargazersViewModel.class); RepoStargazersViewModel repoStargazersModel = new ViewModelProvider(this).get(RepoStargazersViewModel.class);
repoStargazersModel.getRepoStargazers(instanceUrl, instanceToken, repoOwner, repoName, ctx).observe(this, new Observer<List<UserInfo>>() { repoStargazersModel.getRepoStargazers(instanceUrl, instanceToken, repoOwner, repoName, getApplicationContext()).observe(this, new Observer<List<UserInfo>>() {
@Override @Override
public void onChanged(@Nullable List<UserInfo> stargazersListMain) { public void onChanged(@Nullable List<UserInfo> stargazersListMain) {
adapter = new RepoStargazersAdapter(ctx, stargazersListMain); adapter = new RepoStargazersAdapter(getApplicationContext(), stargazersListMain);
if(adapter.getCount() > 0) { if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter); mGridView.setAdapter(adapter);
noDataStargazers.setVisibility(View.GONE); noDataStargazers.setVisibility(View.GONE);
@ -93,8 +84,12 @@ public class RepoStargazersActivity extends BaseActivity {
} }
private void initCloseListener() { private void initCloseListener() {
onClickListener = new View.OnClickListener() {
onClickListener = view -> finish(); @Override
public void onClick(View view) {
finish();
}
};
} }
} }

View File

@ -1,20 +1,20 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.view.View; import android.view.View;
import android.widget.GridView; import android.widget.GridView;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.adapters.RepoWatchersAdapter; import org.mian.gitnex.adapters.RepoWatchersAdapter;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo; import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.RepoWatchersViewModel; import org.mian.gitnex.viewmodels.RepoWatchersViewModel;
import java.util.List; import java.util.List;
@ -22,7 +22,7 @@ import java.util.List;
* Author M M Arif * Author M M Arif
*/ */
public class RepoWatchersActivity extends BaseActivity { public class RepoWatchersActivity extends AppCompatActivity {
private TextView noDataWatchers; private TextView noDataWatchers;
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
@ -30,21 +30,12 @@ public class RepoWatchersActivity extends BaseActivity {
private GridView mGridView; private GridView mGridView;
private ProgressBar mProgressBar; private ProgressBar mProgressBar;
final Context ctx = this;
private Context appCtx;
@Override @Override
protected int getLayoutResourceId(){ protected void onCreate(Bundle savedInstanceState) {
return R.layout.activity_repo_watchers;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
appCtx = getApplicationContext(); setContentView(R.layout.activity_repo_watchers);
TinyDB tinyDb = new TinyDB(appCtx); TinyDB tinyDb = new TinyDB(getApplicationContext());
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");
@ -65,7 +56,7 @@ public class RepoWatchersActivity extends BaseActivity {
toolbarTitle.setText(R.string.repoWatchersInMenu); toolbarTitle.setText(R.string.repoWatchersInMenu);
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName); fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
} }
@ -73,10 +64,10 @@ public class RepoWatchersActivity extends BaseActivity {
RepoWatchersViewModel repoWatchersModel = new ViewModelProvider(this).get(RepoWatchersViewModel.class); RepoWatchersViewModel repoWatchersModel = new ViewModelProvider(this).get(RepoWatchersViewModel.class);
repoWatchersModel.getRepoWatchers(instanceUrl, instanceToken, repoOwner, repoName, ctx).observe(this, new Observer<List<UserInfo>>() { repoWatchersModel.getRepoWatchers(instanceUrl, instanceToken, repoOwner, repoName, getApplicationContext()).observe(this, new Observer<List<UserInfo>>() {
@Override @Override
public void onChanged(@Nullable List<UserInfo> watchersListMain) { public void onChanged(@Nullable List<UserInfo> watchersListMain) {
adapter = new RepoWatchersAdapter(ctx, watchersListMain); adapter = new RepoWatchersAdapter(getApplicationContext(), watchersListMain);
if(adapter.getCount() > 0) { if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter); mGridView.setAdapter(adapter);
noDataWatchers.setVisibility(View.GONE); noDataWatchers.setVisibility(View.GONE);
@ -93,8 +84,12 @@ public class RepoWatchersActivity extends BaseActivity {
} }
private void initCloseListener() { private void initCloseListener() {
onClickListener = new View.OnClickListener() {
onClickListener = view -> finish(); @Override
public void onClick(View view) {
finish();
}
};
} }
} }

View File

@ -1,333 +0,0 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
/**
* Author M M Arif
*/
public class SettingsAppearanceActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
private static String[] timeList = {"Pretty", "Normal"};
private static int timeSelectedChoice = 0;
private static String[] codeBlockList = {"Green - Black", "White - Black", "Grey - Black", "White - Grey", "Dark - White"};
private static int codeBlockSelectedChoice = 0;
private static String[] homeScreenList = {"My Repositories", "Starred Repositories", "Organizations", "Repositories", "Profile", "Explore", "Drafts"};
private static String[] homeScreenListNew = {"My Repositories", "Starred Repositories", "Organizations", "Repositories", "Profile", "Explore", "Drafts", "Notifications"};
private static int homeScreenSelectedChoice = 0;
private static String[] customFontList = {"Roboto", "Manrope", "Source Code Pro"};
private static int customFontSelectedChoice = 0;
private static String[] themeList = {"Dark", "Light", "Auto (Light / Dark)", "Retro", "Auto (Retro / Dark)"};
private static int themeSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_appearance;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
final TinyDB tinyDb = new TinyDB(appCtx);
ImageView closeActivity = findViewById(R.id.close);
final TextView tvDateTimeSelected = findViewById(R.id.tvDateTimeSelected); // setter for time
final TextView codeBlockSelected = findViewById(R.id.codeBlockSelected); // setter for code block
final TextView homeScreenSelected = findViewById(R.id.homeScreenSelected); // setter for home screen
final TextView customFontSelected = findViewById(R.id.customFontSelected); // setter for custom font
final TextView themeSelected = findViewById(R.id.themeSelected); // setter for theme
LinearLayout timeFrame = findViewById(R.id.timeFrame);
LinearLayout codeBlockFrame = findViewById(R.id.codeBlockFrame);
LinearLayout homeScreenFrame = findViewById(R.id.homeScreenFrame);
LinearLayout customFontFrame = findViewById(R.id.customFontFrame);
LinearLayout themeFrame = findViewById(R.id.themeSelectionFrame);
Switch counterBadgesSwitch = findViewById(R.id.switchCounterBadge);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.3")) {
homeScreenList = homeScreenListNew;
}
if(!tinyDb.getString("timeStr").isEmpty()) {
tvDateTimeSelected.setText(tinyDb.getString("timeStr"));
}
if(!tinyDb.getString("codeBlockStr").isEmpty()) {
codeBlockSelected.setText(tinyDb.getString("codeBlockStr"));
}
if(!tinyDb.getString("homeScreenStr").isEmpty()) {
homeScreenSelected.setText(tinyDb.getString("homeScreenStr"));
}
if(!tinyDb.getString("customFontStr").isEmpty()) {
customFontSelected.setText(tinyDb.getString("customFontStr"));
}
if(!tinyDb.getString("themeStr").isEmpty()) {
themeSelected.setText(tinyDb.getString("themeStr"));
}
if(timeSelectedChoice == 0) {
timeSelectedChoice = tinyDb.getInt("timeId");
}
if(codeBlockSelectedChoice == 0) {
codeBlockSelectedChoice = tinyDb.getInt("codeBlockId");
}
if(homeScreenSelectedChoice == 0) {
homeScreenSelectedChoice = tinyDb.getInt("homeScreenId");
}
if(customFontSelectedChoice == 0) {
customFontSelectedChoice = tinyDb.getInt("customFontId", 1);
}
if(themeSelectedChoice == 0) {
themeSelectedChoice = tinyDb.getInt("themeId");
}
if(tinyDb.getBoolean("enableCounterBadges")) {
counterBadgesSwitch.setChecked(true);
}
else {
counterBadgesSwitch.setChecked(false);
}
// counter badge switcher
counterBadgesSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
tinyDb.putBoolean("enableCounterBadges", true);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
else {
tinyDb.putBoolean("enableCounterBadges", false);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
}
});
// theme selection dialog
themeFrame.setOnClickListener(view -> {
AlertDialog.Builder tsBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
tsBuilder.setTitle(getResources().getString(R.string.themeSelectorDialogTitle));
if(themeSelectedChoice != -1) {
tsBuilder.setCancelable(true);
}
else {
tsBuilder.setCancelable(false);
}
tsBuilder.setSingleChoiceItems(themeList, themeSelectedChoice, (dialogInterfaceTheme, i) -> {
themeSelectedChoice = i;
themeSelected.setText(themeList[i]);
tinyDb.putString("themeStr", themeList[i]);
tinyDb.putInt("themeId", i);
tinyDb.putBoolean("refreshParent", true);
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceTheme.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = tsBuilder.create();
cfDialog.show();
});
// custom font dialog
customFontFrame.setOnClickListener(view -> {
AlertDialog.Builder cfBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
cfBuilder.setTitle(R.string.settingsCustomFontSelectorDialogTitle);
if(customFontSelectedChoice != -1) {
cfBuilder.setCancelable(true);
}
else {
cfBuilder.setCancelable(false);
}
cfBuilder.setSingleChoiceItems(customFontList, customFontSelectedChoice, (dialogInterfaceCustomFont, i) -> {
customFontSelectedChoice = i;
customFontSelected.setText(customFontList[i]);
tinyDb.putString("customFontStr", customFontList[i]);
tinyDb.putInt("customFontId", i);
tinyDb.putBoolean("refreshParent", true);
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceCustomFont.dismiss();
Toasty.success(appCtx, appCtx.getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = cfBuilder.create();
cfDialog.show();
});
// home screen dialog
homeScreenFrame.setOnClickListener(view -> {
AlertDialog.Builder hsBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
hsBuilder.setTitle(R.string.settingsHomeScreenSelectorDialogTitle);
if(homeScreenSelectedChoice != -1) {
hsBuilder.setCancelable(true);
}
else {
hsBuilder.setCancelable(false);
}
hsBuilder.setSingleChoiceItems(homeScreenList, homeScreenSelectedChoice, (dialogInterfaceHomeScreen, i) -> {
homeScreenSelectedChoice = i;
homeScreenSelected.setText(homeScreenList[i]);
tinyDb.putString("homeScreenStr", homeScreenList[i]);
tinyDb.putInt("homeScreenId", i);
dialogInterfaceHomeScreen.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog hsDialog = hsBuilder.create();
hsDialog.show();
});
// code block dialog
codeBlockFrame.setOnClickListener(view -> {
AlertDialog.Builder cBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
cBuilder.setTitle(R.string.settingsCodeBlockSelectorDialogTitle);
if(codeBlockSelectedChoice != -1) {
cBuilder.setCancelable(true);
}
else {
cBuilder.setCancelable(false);
}
cBuilder.setSingleChoiceItems(codeBlockList, codeBlockSelectedChoice, (dialogInterfaceCodeBlock, i) -> {
codeBlockSelectedChoice = i;
codeBlockSelected.setText(codeBlockList[i]);
tinyDb.putString("codeBlockStr", codeBlockList[i]);
tinyDb.putInt("codeBlockId", i);
switch(codeBlockList[i]) {
case "White - Black":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorWhite));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
break;
case "Grey - Black":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorAccent));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
break;
case "White - Grey":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorWhite));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.colorAccent));
break;
case "Dark - White":
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorPrimary));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.colorWhite));
break;
default:
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorLightGreen));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
break;
}
dialogInterfaceCodeBlock.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cDialog = cBuilder.create();
cDialog.show();
});
// time and date dialog
timeFrame.setOnClickListener(view -> {
AlertDialog.Builder tBuilder = new AlertDialog.Builder(SettingsAppearanceActivity.this);
tBuilder.setTitle(R.string.settingsTimeSelectorDialogTitle);
if(timeSelectedChoice != -1) {
tBuilder.setCancelable(true);
}
else {
tBuilder.setCancelable(false);
}
tBuilder.setSingleChoiceItems(timeList, timeSelectedChoice, (dialogInterfaceTime, i) -> {
timeSelectedChoice = i;
tvDateTimeSelected.setText(timeList[i]);
tinyDb.putString("timeStr", timeList[i]);
tinyDb.putInt("timeId", i);
if("Normal".equals(timeList[i])) {
tinyDb.putString("dateFormat", "normal");
}
else {
tinyDb.putString("dateFormat", "pretty");
}
dialogInterfaceTime.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog tDialog = tBuilder.create();
tDialog.show();
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

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

View File

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

View File

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

View File

@ -1,261 +0,0 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import org.apache.commons.io.FileUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.FilesData;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.helpers.ssl.MemorizingTrustManager;
import org.mian.gitnex.notifications.NotificationsMaster;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
/**
* Author M M Arif
*/
public class SettingsSecurityActivity extends BaseActivity {
private Context appCtx;
private Context ctx = this;
private View.OnClickListener onClickListener;
private static String[] cacheSizeDataList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"};
private static int cacheSizeDataSelectedChoice = 0;
private static String[] cacheSizeImagesList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"};
private static int cacheSizeImagesSelectedChoice = 0;
private static int MINIMUM_POLLING_DELAY = 1;
private static int DEFAULT_POLLING_DELAY = 20;
private static int MAXIMUM_POLLING_DELAY = 720;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_security;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
String currentVersion = tinyDb.getString("giteaVersion");
ImageView closeActivity = findViewById(R.id.close);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
TextView cacheSizeDataSelected = findViewById(R.id.cacheSizeDataSelected); // setter for data cache size
TextView cacheSizeImagesSelected = findViewById(R.id.cacheSizeImagesSelected); // setter for images cache size
TextView clearCacheSelected = findViewById(R.id.clearCacheSelected); // setter for clear cache
TextView pollingDelaySelected = findViewById(R.id.pollingDelaySelected);
LinearLayout certsFrame = findViewById(R.id.certsFrame);
LinearLayout pollingDelayFrame = findViewById(R.id.pollingDelayFrame);
LinearLayout cacheSizeDataFrame = findViewById(R.id.cacheSizeDataSelectionFrame);
LinearLayout cacheSizeImagesFrame = findViewById(R.id.cacheSizeImagesSelectionFrame);
LinearLayout clearCacheFrame = findViewById(R.id.clearCacheSelectionFrame);
if(!tinyDb.getString("cacheSizeStr").isEmpty()) {
cacheSizeDataSelected.setText(tinyDb.getString("cacheSizeStr"));
}
if(!tinyDb.getString("cacheSizeImagesStr").isEmpty()) {
cacheSizeImagesSelected.setText(tinyDb.getString("cacheSizeImagesStr"));
}
if(cacheSizeDataSelectedChoice == 0) {
cacheSizeDataSelectedChoice = tinyDb.getInt("cacheSizeId");
}
if(cacheSizeImagesSelectedChoice == 0) {
cacheSizeImagesSelectedChoice = tinyDb.getInt("cacheSizeImagesId");
}
if(new Version(currentVersion).less("1.12.3")) {
pollingDelayFrame.setVisibility(View.GONE);
}
pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), tinyDb.getInt("pollingDelayMinutes", DEFAULT_POLLING_DELAY)));
// clear cache setter
File cacheDir = appCtx.getCacheDir();
long size__ = FilesData.getFileSizeRecursively(new HashSet<>(), cacheDir);
if(size__ > 0) {
clearCacheSelected.setText(String.valueOf(AppUtil.formatFileSizeInDetail(size__)));
}
// clear cache
clearCacheFrame.setOnClickListener(v1 -> {
AlertDialog.Builder builder = new AlertDialog.Builder(SettingsSecurityActivity.this);
builder.setTitle(getResources().getString(R.string.clearCacheDialogHeader));
builder.setMessage(getResources().getString(R.string.clearCacheDialogMessage));
builder.setPositiveButton(R.string.menuDeleteText, (dialog, which) -> {
try {
FileUtils.deleteDirectory(cacheDir);
FileUtils.mkdir(cacheDir.getAbsolutePath());
this.recreate();
this.overridePendingTransition(0, 0);
}
catch (IOException e) {
Log.e("SettingsSecurity", e.toString());
}
});
builder.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss());
builder.create().show();
});
// cache size images selection dialog
cacheSizeImagesFrame.setOnClickListener(view -> {
AlertDialog.Builder tsBuilder = new AlertDialog.Builder(SettingsSecurityActivity.this);
tsBuilder.setTitle(getResources().getString(R.string.cacheSizeImagesDialogHeader));
if(cacheSizeImagesSelectedChoice != -1) {
tsBuilder.setCancelable(true);
}
else {
tsBuilder.setCancelable(false);
}
tsBuilder.setSingleChoiceItems(cacheSizeImagesList, cacheSizeImagesSelectedChoice, (dialogInterfaceTheme, i) -> {
cacheSizeImagesSelectedChoice = i;
cacheSizeImagesSelected.setText(cacheSizeImagesList[i]);
tinyDb.putString("cacheSizeImagesStr", cacheSizeImagesList[i]);
tinyDb.putInt("cacheSizeImagesId", i);
dialogInterfaceTheme.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = tsBuilder.create();
cfDialog.show();
});
// cache size data selection dialog
cacheSizeDataFrame.setOnClickListener(view -> {
AlertDialog.Builder tsBuilder = new AlertDialog.Builder(SettingsSecurityActivity.this);
tsBuilder.setTitle(getResources().getString(R.string.cacheSizeDataDialogHeader));
if(cacheSizeDataSelectedChoice != -1) {
tsBuilder.setCancelable(true);
}
else {
tsBuilder.setCancelable(false);
}
tsBuilder.setSingleChoiceItems(cacheSizeDataList, cacheSizeDataSelectedChoice, (dialogInterfaceTheme, i) -> {
cacheSizeDataSelectedChoice = i;
cacheSizeDataSelected.setText(cacheSizeDataList[i]);
tinyDb.putString("cacheSizeStr", cacheSizeDataList[i]);
tinyDb.putInt("cacheSizeId", i);
dialogInterfaceTheme.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog cfDialog = tsBuilder.create();
cfDialog.show();
});
// certs deletion
certsFrame.setOnClickListener(v1 -> {
AlertDialog.Builder builder = new AlertDialog.Builder(SettingsSecurityActivity.this);
builder.setTitle(getResources().getString(R.string.settingsCertsPopupTitle));
builder.setMessage(getResources().getString(R.string.settingsCertsPopupMessage));
builder.setPositiveButton(R.string.menuDeleteText, (dialog, which) -> {
appCtx.getSharedPreferences(MemorizingTrustManager.KEYSTORE_NAME, Context.MODE_PRIVATE).edit().remove(MemorizingTrustManager.KEYSTORE_KEY).apply();
tinyDb.putBoolean("loggedInMode", false);
tinyDb.remove("basicAuthPassword");
tinyDb.putBoolean("basicAuthFlag", false);
Intent loginActivityIntent = new Intent().setClass(appCtx, LoginActivity.class);
loginActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
appCtx.startActivity(loginActivityIntent);
});
builder.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss());
builder.create().show();
});
// polling delay
pollingDelayFrame.setOnClickListener(v -> {
NumberPicker numberPicker = new NumberPicker(ctx);
numberPicker.setMinValue(MINIMUM_POLLING_DELAY);
numberPicker.setMaxValue(MAXIMUM_POLLING_DELAY);
numberPicker.setValue(tinyDb.getInt("pollingDelayMinutes", DEFAULT_POLLING_DELAY));
numberPicker.setWrapSelectorWheel(true);
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle(getString(R.string.pollingDelayDialogHeaderText));
builder.setMessage(getString(R.string.pollingDelayDialogDescriptionText));
builder.setCancelable(true);
builder.setPositiveButton(getString(R.string.okButton), (dialog, which) -> {
tinyDb.putInt("pollingDelayMinutes", numberPicker.getValue());
NotificationsMaster.fireWorker(ctx);
NotificationsMaster.hireWorker(ctx);
pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), numberPicker.getValue()));
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
builder.setNeutralButton(R.string.cancelButton, null);
builder.setView(numberPicker);
builder.create().show();
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -1,163 +0,0 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
/**
* Author M M Arif
*/
public class SettingsTranslationActivity extends BaseActivity {
private Context appCtx;
private View.OnClickListener onClickListener;
private static String[] langList = {"English", "Arabic", "Chinese", "Finnish", "French", "German", "Italian", "Latvian", "Persian", "Polish", "Portuguese/Brazilian", "Russian", "Serbian", "Spanish", "Turkish",
"Ukrainian"};
private static int langSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_translation;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
TinyDB tinyDb = new TinyDB(appCtx);
ImageView closeActivity = findViewById(R.id.close);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
final TextView tvLanguageSelected = findViewById(R.id.tvLanguageSelected); // setter for en, fr
TextView helpTranslate = findViewById(R.id.helpTranslate);
LinearLayout langFrame = findViewById(R.id.langFrame);
helpTranslate.setOnClickListener(v12 -> {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse(getResources().getString(R.string.crowdInLink)));
startActivity(intent);
});
if(!tinyDb.getString("localeStr").isEmpty()) {
tvLanguageSelected.setText(tinyDb.getString("localeStr"));
}
if(langSelectedChoice == 0) {
langSelectedChoice = tinyDb.getInt("langId");
}
// language dialog
langFrame.setOnClickListener(view -> {
AlertDialog.Builder lBuilder = new AlertDialog.Builder(SettingsTranslationActivity.this);
lBuilder.setTitle(R.string.settingsLanguageSelectorDialogTitle);
if(langSelectedChoice != -1) {
lBuilder.setCancelable(true);
}
else {
lBuilder.setCancelable(false);
}
lBuilder.setSingleChoiceItems(langList, langSelectedChoice, (dialogInterface, i) -> {
langSelectedChoice = i;
tvLanguageSelected.setText(langList[i]);
tinyDb.putString("localeStr", langList[i]);
tinyDb.putInt("langId", i);
switch(langList[i]) {
case "Arabic":
tinyDb.putString("locale", "ar");
break;
case "Chinese":
tinyDb.putString("locale", "zh");
break;
case "Finnish":
tinyDb.putString("locale", "fi");
break;
case "French":
tinyDb.putString("locale", "fr");
break;
case "German":
tinyDb.putString("locale", "de");
break;
case "Italian":
tinyDb.putString("locale", "it");
break;
case "Latvian":
tinyDb.putString("locale", "lv");
break;
case "Persian":
tinyDb.putString("locale", "fa");
break;
case "Polish":
tinyDb.putString("locale", "pl");
break;
case "Portuguese/Brazilian":
tinyDb.putString("locale", "pt");
break;
case "Russian":
tinyDb.putString("locale", "ru");
break;
case "Serbian":
tinyDb.putString("locale", "sr");
break;
case "Spanish":
tinyDb.putString("locale", "es");
break;
case "Turkish":
tinyDb.putString("locale", "tr");
break;
case "Ukrainian":
tinyDb.putString("locale", "uk");
break;
default:
tinyDb.putString("locale", "en");
break;
}
tinyDb.putBoolean("refreshParent", true);
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterface.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
lBuilder.setNeutralButton(getString(R.string.cancelButton), null);
AlertDialog lDialog = lBuilder.create();
lDialog.show();
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

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

View File

@ -11,8 +11,8 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo; import org.mian.gitnex.models.UserInfo;
import java.util.ArrayList; import java.util.ArrayList;
@ -57,7 +57,7 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
@NonNull @NonNull
@Override @Override
public AdminGetUsersAdapter.UsersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public AdminGetUsersAdapter.UsersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_admin_users, parent, false); View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.admin_users_list, parent, false);
return new AdminGetUsersAdapter.UsersViewHolder(v); return new AdminGetUsersAdapter.UsersViewHolder(v);
} }
@ -86,7 +86,7 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
holder.userRole.setVisibility(View.VISIBLE); holder.userRole.setVisibility(View.VISIBLE);
TextDrawable drawable = TextDrawable.builder() TextDrawable drawable = TextDrawable.builder()
.beginConfig() .beginConfig()
.textColor(mCtx.getResources().getColor(R.color.colorWhite)) .textColor(mCtx.getResources().getColor(R.color.white))
.fontSize(44) .fontSize(44)
.width(180) .width(180)
.height(60) .height(60)
@ -98,7 +98,7 @@ public class AdminGetUsersAdapter extends RecyclerView.Adapter<AdminGetUsersAdap
holder.userRole.setVisibility(View.GONE); holder.userRole.setVisibility(View.GONE);
} }
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar); Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
} }
@Override @Override

View File

@ -1,20 +1,18 @@
package org.mian.gitnex.adapters; package org.mian.gitnex.adapters;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.CommitsActivity;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Branches;
import java.util.List;
import java.util.Objects;
/** /**
* Author M M Arif * Author M M Arif
@ -29,23 +27,14 @@ public class BranchesAdapter extends RecyclerView.Adapter<BranchesAdapter.Branch
private TextView branchNameTv; private TextView branchNameTv;
private TextView branchCommitAuthor; private TextView branchCommitAuthor;
private TextView branchCommitHash;
private BranchesViewHolder(View itemView) { private BranchesViewHolder(View itemView) {
super(itemView); super(itemView);
branchNameTv = itemView.findViewById(R.id.branchName); branchNameTv = itemView.findViewById(R.id.branchName);
branchCommitAuthor = itemView.findViewById(R.id.branchCommitAuthor); branchCommitAuthor = itemView.findViewById(R.id.branchCommitAuthor);
Button branchCommitHash = itemView.findViewById(R.id.branchCommitHash); branchCommitHash = itemView.findViewById(R.id.branchCommitHash);
branchCommitHash.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), CommitsActivity.class);
intent.putExtra("branchName", String.valueOf(branchNameTv.getText()));
Objects.requireNonNull(v.getContext()).startActivity(intent);
}
});
} }
} }
@ -58,7 +47,7 @@ public class BranchesAdapter extends RecyclerView.Adapter<BranchesAdapter.Branch
@NonNull @NonNull
@Override @Override
public BranchesAdapter.BranchesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public BranchesAdapter.BranchesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_branches, parent, false); View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.branches_list, parent, false);
return new BranchesAdapter.BranchesViewHolder(v); return new BranchesAdapter.BranchesViewHolder(v);
} }
@ -78,6 +67,10 @@ public class BranchesAdapter extends RecyclerView.Adapter<BranchesAdapter.Branch
holder.branchCommitAuthor.setText(mCtx.getResources().getString(R.string.commitAuthor, currentItem.getCommit().getAuthor().getUsername())); holder.branchCommitAuthor.setText(mCtx.getResources().getString(R.string.commitAuthor, currentItem.getCommit().getAuthor().getUsername()));
} }
holder.branchCommitHash.setText(
Html.fromHtml("<a href='" + currentItem.getCommit().getUrl() + "'>" + mCtx.getResources().getString(R.string.commitLinkBranchesTab) + "</a> "));
holder.branchCommitHash.setMovementMethod(LinkMovementMethod.getInstance());
} }
@Override @Override

View File

@ -0,0 +1,291 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.util.TinyDB;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
/**
* Author M M Arif
*/
public class ClosedIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {
private Context context;
private final int TYPE_LOAD = 0;
private List<Issues> issuesList;
private List<Issues> issuesListFull;
private ClosedIssuesAdapter.OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public ClosedIssuesAdapter(Context context, List<Issues> issuesListMain) {
this.context = context;
this.issuesList = issuesListMain;
issuesListFull = new ArrayList<>(issuesList);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType == TYPE_LOAD){
return new ClosedIssuesAdapter.IssuesHolder(inflater.inflate(R.layout.repo_detail_issues_list, parent,false));
}
else {
return new ClosedIssuesAdapter.LoadHolder(inflater.inflate(R.layout.row_load,parent,false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount()-1 && isMoreDataAvailable && !isLoading && loadMoreListener!=null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((ClosedIssuesAdapter.IssuesHolder)holder).bindData(issuesList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(issuesList.get(position).getTitle() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return issuesList.size();
}
class IssuesHolder extends RecyclerView.ViewHolder {
private TextView issueNumber;
private ImageView issueAssigneeAvatar;
private TextView issueTitle;
private TextView issueCreatedTime;
private TextView issueCommentsCount;
private RelativeLayout relativeLayoutFrame;
IssuesHolder(View itemView) {
super(itemView);
issueNumber = itemView.findViewById(R.id.issueNumber);
issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
issueTitle = itemView.findViewById(R.id.issueTitle);
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount);
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
relativeLayoutFrame = itemView.findViewById(R.id.relativeLayoutFrame);
issueTitle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
//Log.i("issueNumber", issueNumber.getText().toString());
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText());
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "issue");
context.startActivity(intent);
}
});
frameCommentsCount.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
//Log.i("issueNumber", issueNumber.getText().toString());
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText());
TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "issue");
context.startActivity(intent);
}
});
}
@SuppressLint("SetTextI18n")
void bindData(Issues issuesModel){
final TinyDB tinyDb = new TinyDB(context);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
/*if(issuesModel.getPull_request() != null) {
if (issuesModel.getPull_request().isMerged()) {
relativeLayoutFrame.setVisibility(View.GONE);
relativeLayoutFrame.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
}
}*/
if (!issuesModel.getUser().getFull_name().equals("")) {
issueAssigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueCreator) + issuesModel.getUser().getFull_name(), context));
} else {
issueAssigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueCreator) + issuesModel.getUser().getLogin(), context));
}
if (issuesModel.getUser().getAvatar_url() != null) {
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar);
} else {
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar);
}
String issueNumber_ = "<font color='" + context.getResources().getColor(R.color.lightGray) + "'>" + context.getResources().getString(R.string.hash) + issuesModel.getNumber() + "</font>";
issueTitle.setText(Html.fromHtml(issueNumber_ + " " + issuesModel.getTitle()));
issueNumber.setText(String.valueOf(issuesModel.getNumber()));
issueCommentsCount.setText(String.valueOf(issuesModel.getComments()));
switch (timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(issuesModel.getCreated_at()), context));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
break;
}
}
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(ClosedIssuesAdapter.OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
@Override
public Filter getFilter() {
return issuesFilter;
}
private Filter issuesFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Issues> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(issuesList);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (Issues item : issuesList) {
if (item.getTitle().toLowerCase().contains(filterPattern) || item.getBody().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
issuesList.clear();
issuesList.addAll((List) results.values);
notifyDataSetChanged();
}
};
}

View File

@ -8,8 +8,8 @@ import android.view.ViewGroup;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.models.Collaborators; import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import java.util.List; import java.util.List;
@ -61,7 +61,7 @@ public class CollaboratorsAdapter extends BaseAdapter {
ViewHolder viewHolder = null; ViewHolder viewHolder = null;
if (finalView == null) { if (finalView == null) {
finalView = LayoutInflater.from(mCtx).inflate(R.layout.list_collaborators, null); finalView = LayoutInflater.from(mCtx).inflate(R.layout.collaborators_list, null);
viewHolder = new ViewHolder(finalView); viewHolder = new ViewHolder(finalView);
finalView.setTag(viewHolder); finalView.setTag(viewHolder);
} }
@ -77,7 +77,7 @@ public class CollaboratorsAdapter extends BaseAdapter {
private void initData(ViewHolder viewHolder, int position) { private void initData(ViewHolder viewHolder, int position) {
Collaborators currentItem = collaboratorsList.get(position); Collaborators currentItem = collaboratorsList.get(position);
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.collaboratorAvatar); Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.collaboratorAvatar);
if(!currentItem.getFull_name().equals("")) { if(!currentItem.getFull_name().equals("")) {
viewHolder.collaboratorName.setText(currentItem.getFull_name()); viewHolder.collaboratorName.setText(currentItem.getFull_name());

View File

@ -1,174 +0,0 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Commits;
import java.util.List;
import java.util.Locale;
/**
* Author M M Arif
*/
public class CommitsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context ctx;
private final int TYPE_LOAD = 0;
private List<Commits> commitsList;
private CommitsAdapter.OnLoadMoreListener loadMoreListener;
private boolean isLoading = false;
private boolean isMoreDataAvailable = true;
public CommitsAdapter(Context ctx, List<Commits> commitsListMain) {
this.ctx = ctx;
this.commitsList = commitsListMain;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(ctx);
if(viewType == TYPE_LOAD) {
return new CommitsHolder(inflater.inflate(R.layout.list_commits, parent, false));
}
else {
return new LoadHolder(inflater.inflate(R.layout.row_load, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((CommitsHolder) holder).bindData(commitsList.get(position));
}
}
@Override
public int getItemViewType(int position) {
if(commitsList.get(position).getSha() != null) {
return TYPE_LOAD;
}
else {
return 1;
}
}
@Override
public int getItemCount() {
return commitsList.size();
}
class CommitsHolder extends RecyclerView.ViewHolder {
TextView commitTitle;
TextView commitCommitter;
TextView commitDate;
Button commitHtmlUrl;
CommitsHolder(View itemView) {
super(itemView);
commitTitle = itemView.findViewById(R.id.commitTitleVw);
commitCommitter = itemView.findViewById(R.id.commitCommitterVw);
commitDate = itemView.findViewById(R.id.commitDateVw);
commitHtmlUrl = itemView.findViewById(R.id.commitHtmlUrlVw);
}
@SuppressLint("SetTextI18n")
void bindData(Commits commitsModel) {
final TinyDB tinyDb = new TinyDB(ctx);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
commitTitle.setText(commitsModel.getCommit().getMessage());
commitCommitter.setText(ctx.getString(R.string.commitCommittedBy, commitsModel.getCommit().getCommitter().getName()));
commitDate.setText(TimeHelper.formatTime(commitsModel.getCommit().getCommitter().getDate(), new Locale(locale), timeFormat, ctx));
if(timeFormat.equals("pretty")) {
commitDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(commitsModel.getCommit().getCommitter().getDate()), ctx));
}
commitHtmlUrl.setOnClickListener(v -> ctx.startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse(commitsModel.getHtml_url()))));
}
}
static class LoadHolder extends RecyclerView.ViewHolder {
LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(CommitsAdapter.OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<Commits> list) {
commitsList = list;
notifyDataSetChanged();
}
}

View File

@ -1,158 +0,0 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.database.models.DraftWithRepository;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.List;
/**
* Author M M Arif
*/
public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsViewHolder> {
private List<DraftWithRepository> draftsList;
private Context mCtx;
class DraftsViewHolder extends RecyclerView.ViewHolder {
private TextView draftText;
private TextView repoInfo;
private TextView repoId;
private TextView draftId;
private TextView issueNumber;
private TextView issueType;
private TextView repoOwner;
private TextView repoName;
private TextView commentId;
private ImageView editCommentStatus;
private DraftsViewHolder(View itemView) {
super(itemView);
draftText = itemView.findViewById(R.id.draftText);
repoInfo = itemView.findViewById(R.id.repoInfo);
repoId = itemView.findViewById(R.id.repoId);
draftId = itemView.findViewById(R.id.draftId);
issueNumber = itemView.findViewById(R.id.issueNumber);
issueType = itemView.findViewById(R.id.issueType);
repoOwner = itemView.findViewById(R.id.repoOwner);
repoName = itemView.findViewById(R.id.repoName);
commentId = itemView.findViewById(R.id.commentId);
ImageView deleteDraft = itemView.findViewById(R.id.deleteDraft);
editCommentStatus = itemView.findViewById(R.id.editCommentStatus);
deleteDraft.setOnClickListener(itemDelete -> {
int getDraftId = Integer.parseInt(draftId.getText().toString());
deleteDraft(getAdapterPosition());
DraftsApi draftsApi = new DraftsApi(mCtx);
draftsApi.deleteSingleDraft(getDraftId);
});
itemView.setOnClickListener(itemEdit -> {
Intent intent = new Intent(mCtx, ReplyToIssueActivity.class);
intent.putExtra("commentBody", draftText.getText().toString());
intent.putExtra("issueNumber", issueNumber.getText().toString());
intent.putExtra("repositoryId", repoId.getText().toString());
intent.putExtra("draftTitle", repoInfo.getText().toString());
intent.putExtra("commentId", commentId.getText().toString());
intent.putExtra("draftId", draftId.getText().toString());
if(!commentId.getText().toString().equalsIgnoreCase("")) {
intent.putExtra("commentAction", "edit");
}
TinyDB tinyDb = new TinyDB(mCtx);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putLong("repositoryId", Long.parseLong(repoId.getText().toString()));
//tinyDb.putString("issueType", issueType.getText().toString());
mCtx.startActivity(intent);
});
}
}
public DraftsAdapter(Context mCtx, List<DraftWithRepository> draftsListMain) {
this.mCtx = mCtx;
this.draftsList = draftsListMain;
}
private void deleteDraft(int position) {
draftsList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, draftsList.size());
Toasty.success(mCtx, mCtx.getResources().getString(R.string.draftsSingleDeleteSuccess));
}
@NonNull
@Override
public DraftsAdapter.DraftsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_drafts, parent, false);
return new DraftsViewHolder(v);
}
@SuppressLint("DefaultLocale")
@Override
public void onBindViewHolder(@NonNull DraftsAdapter.DraftsViewHolder holder, int position) {
DraftWithRepository currentItem = draftsList.get(position);
holder.repoId.setText(String.valueOf(currentItem.getRepositoryId()));
holder.draftId.setText(String.valueOf(currentItem.getDraftId()));
holder.issueNumber.setText(String.valueOf(currentItem.getIssueId()));
holder.issueType.setText(currentItem.getDraftType());
holder.repoOwner.setText(currentItem.getRepositoryOwner());
holder.repoName.setText(currentItem.getRepositoryName());
holder.draftText.setText(currentItem.getDraftText());
holder.commentId.setText(currentItem.getCommentId());
String issueNumber = "<font color='" + mCtx.getResources().getColor(R.color.lightGray) + "'>" + mCtx.getResources().getString(R.string.hash) + currentItem.getIssueId() + "</font>";
Spanned headTitle = Html.fromHtml(issueNumber + " " + currentItem.getRepositoryOwner() + " / " + currentItem.getRepositoryName());
holder.repoInfo.setText(headTitle);
if(!currentItem.getCommentId().equalsIgnoreCase("new")) {
holder.editCommentStatus.setVisibility(View.VISIBLE);
}
else {
holder.editCommentStatus.setVisibility(View.GONE);
}
}
@Override
public int getItemCount() {
return draftsList.size();
}
public void updateList(List<DraftWithRepository> list) {
draftsList = list;
notifyDataSetChanged();
}
}

View File

@ -1,42 +1,31 @@
package org.mian.gitnex.adapters; package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
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.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator; import com.amulyakhare.textdrawable.util.ColorGenerator;
import com.google.android.material.bottomsheet.BottomSheetDialog; import com.squareup.picasso.Picasso;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.OpenRepoInBrowserActivity; import org.mian.gitnex.activities.OpenRepoInBrowserActivity;
import org.mian.gitnex.activities.RepoDetailActivity; import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.RepoForksActivity;
import org.mian.gitnex.activities.RepoStargazersActivity; import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity; import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories; import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchInfo; import org.mian.gitnex.util.TinyDB;
import java.lang.reflect.Field;
import java.util.List; import java.util.List;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
/** /**
* Author M M Arif * Author M M Arif
@ -44,278 +33,184 @@ import retrofit2.Callback;
public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepositoriesAdapter.ReposSearchViewHolder> { public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepositoriesAdapter.ReposSearchViewHolder> {
private List<UserRepositories> searchedReposList;
private Context mCtx;
public ExploreRepositoriesAdapter(List<UserRepositories> dataList, Context mCtx) { private List<UserRepositories> searchedReposList;
private Context mCtx;
this.mCtx = mCtx; public ExploreRepositoriesAdapter(List<UserRepositories> dataList, Context mCtx) {
this.searchedReposList = dataList; this.mCtx = mCtx;
} this.searchedReposList = dataList;
}
static class ReposSearchViewHolder extends RecyclerView.ViewHolder { static class ReposSearchViewHolder extends RecyclerView.ViewHolder {
private ImageView image; private ImageView image;
private TextView repoName; private TextView mTextView1;
private TextView repoDescription; private TextView mTextView2;
private TextView fullName; private TextView fullName;
private CheckBox isRepoAdmin; private ImageView repoPrivatePublic;
private ImageView repoPrivatePublic; 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 TextView repoBranch;
private TextView htmlUrl;
private ReposSearchViewHolder(View itemView) { private ReposSearchViewHolder(View itemView) {
super(itemView);
super(itemView); mTextView1 = itemView.findViewById(R.id.repoName);
mTextView2 = itemView.findViewById(R.id.repoDescription);
image = itemView.findViewById(R.id.imageAvatar);
fullName = itemView.findViewById(R.id.repoFullName);
repoPrivatePublic = itemView.findViewById(R.id.imageRepoType);
repoStars = itemView.findViewById(R.id.repoStars);
repoForks = itemView.findViewById(R.id.repoForks);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoName = itemView.findViewById(R.id.repoName); itemView.setOnClickListener(new View.OnClickListener() {
repoDescription = itemView.findViewById(R.id.repoDescription); @Override
image = itemView.findViewById(R.id.imageAvatar); public void onClick(View v) {
fullName = itemView.findViewById(R.id.repoFullName);
isRepoAdmin = itemView.findViewById(R.id.repoIsAdmin);
repoPrivatePublic = itemView.findViewById(R.id.imageRepoType);
repoStars = itemView.findViewById(R.id.repoStars);
repoForks = itemView.findViewById(R.id.repoForks);
repoOpenIssuesCount = itemView.findViewById(R.id.repoOpenIssuesCount);
ImageView reposDropdownMenu = itemView.findViewById(R.id.reposDropdownMenu);
repoType = itemView.findViewById(R.id.repoType);
archiveRepo = itemView.findViewById(R.id.archiveRepoFrame);
repoBranch = itemView.findViewById(R.id.repoBranch);
htmlUrl = itemView.findViewById(R.id.htmlUrl);
itemView.setOnClickListener(v -> { Context context = v.getContext();
TextView repoFullName = v.findViewById(R.id.repoFullName);
Context context = v.getContext(); Intent intent = new Intent(context, RepoDetailActivity.class);
TextView repoFullName = v.findViewById(R.id.repoFullName); intent.putExtra("repoFullName", repoFullName.getText().toString());
Intent intent = new Intent(context, RepoDetailActivity.class); TinyDB tinyDb = new TinyDB(context);
intent.putExtra("repoFullName", repoFullName.getText().toString()); tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putBoolean("resumeIssues", true);
context.startActivity(intent);
TinyDB tinyDb = new TinyDB(context); }
tinyDb.putString("repoFullName", repoFullName.getText().toString()); });
tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
tinyDb.putString("repoBranch", repoBranch.getText().toString());
String[] parts = fullName.getText().toString().split("/"); reposDropdownMenu.setOnClickListener(new View.OnClickListener() {
final String repoOwner = parts[0]; @Override
final String repoName = parts[1]; public void onClick(View v) {
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId"); final Context context = v.getContext();
RepositoriesApi repositoryData = new RepositoriesApi(context); Context context_ = new ContextThemeWrapper(context, R.style.popupMenuStyle);
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchInfo watch = new WatchInfo();
Call<WatchInfo> call;
call = RetrofitClient.getInstance(instanceUrl, context).getApiInterface().checkRepoWatchStatus(token, repoOwner, repoName);
call.enqueue(new Callback<WatchInfo>() {
@Override
public void onResponse(@NonNull Call<WatchInfo> call, @NonNull retrofit2.Response<WatchInfo> response) {
if(response.isSuccessful()) {
assert response.body() != null;
tinyDb.putBoolean("repoWatch", response.body().getSubscribed());
} else {
tinyDb.putBoolean("repoWatch", false);
if(response.code() != 404) {
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
}
}
@Override
public void onFailure(@NonNull Call<WatchInfo> call, @NonNull Throwable t) {
tinyDb.putBoolean("repoWatch", false);
Toasty.error(context, context.getString(R.string.genericApiStatusError));
}
});
}
context.startActivity(intent);
});
reposDropdownMenu.setOnClickListener(v -> {
final Context context = v.getContext();
@SuppressLint("InflateParams") View view = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_repository_in_list, null);
TextView repoOpenInBrowser = view.findViewById(R.id.repoOpenInBrowser);
TextView repoStargazers = view.findViewById(R.id.repoStargazers);
TextView repoWatchers = view.findViewById(R.id.repoWatchers);
TextView repoForksList = view.findViewById(R.id.repoForksList);
TextView repoCopyUrl = view.findViewById(R.id.repoCopyUrl);
TextView bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader);
bottomSheetHeader.setText(String.format("%s / %s", fullName.getText().toString().split("/")[0], fullName.getText().toString().split("/")[1]));
BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view);
dialog.show();
repoCopyUrl.setOnClickListener(openInBrowser -> {
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(context).getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("repoUrl", htmlUrl.getText().toString());
assert clipboard != null;
clipboard.setPrimaryClip(clip);
Toasty.info(context, context.getString(R.string.copyIssueUrlToastMsg));
dialog.dismiss();
});
repoOpenInBrowser.setOnClickListener(openInBrowser -> {
Intent intentOpenInBrowser = new Intent(context, OpenRepoInBrowserActivity.class);
intentOpenInBrowser.putExtra("repoFullNameBrowser", fullName.getText());
context.startActivity(intentOpenInBrowser);
dialog.dismiss();
});
repoStargazers.setOnClickListener(stargazers -> {
Intent intent = new Intent(context, RepoStargazersActivity.class);
intent.putExtra("repoFullNameForStars", fullName.getText());
context.startActivity(intent);
dialog.dismiss();
});
repoWatchers.setOnClickListener(watchers -> {
Intent intentW = new Intent(context, RepoWatchersActivity.class);
intentW.putExtra("repoFullNameForWatchers", fullName.getText());
context.startActivity(intentW);
dialog.dismiss();
});
repoForksList.setOnClickListener(forks -> {
Intent intentW = new Intent(context, RepoForksActivity.class);
intentW.putExtra("repoFullNameForForks", fullName.getText());
context.startActivity(intentW);
dialog.dismiss();
});
});
}
}
@NonNull
@Override
public ExploreRepositoriesAdapter.ReposSearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_repositories, parent, false);
return new ExploreRepositoriesAdapter.ReposSearchViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull final ExploreRepositoriesAdapter.ReposSearchViewHolder holder, int position) {
UserRepositories currentItem = searchedReposList.get(position);
holder.repoDescription.setVisibility(View.GONE);
holder.repoBranch.setText(currentItem.getDefault_branch());
holder.htmlUrl.setText(currentItem.getHtml_url());
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
String firstCharacter = String.valueOf(currentItem.getName().charAt(0));
TextDrawable drawable = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT).fontSize(18).toUpperCase().width(28).height(28).endConfig().buildRoundRect(firstCharacter, color, 3);
if(currentItem.getAvatar_url() != null) {
if(!currentItem.getAvatar_url().equals("")) {
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
}
else {
holder.image.setImageDrawable(drawable);
}
}
else {
holder.image.setImageDrawable(drawable);
}
holder.repoName.setText(currentItem.getName());
if(!currentItem.getDescription().equals("")) {
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullname());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
}
else {
holder.repoPrivatePublic.setVisibility(View.GONE);
holder.repoType.setText(R.string.strPublic);
}
holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count());
holder.repoOpenIssuesCount.setText(currentItem.getOpen_issues_count());
if(holder.isRepoAdmin == null) {
holder.isRepoAdmin = new CheckBox(mCtx);
}
holder.isRepoAdmin.setChecked(currentItem.getPermissions().isAdmin());
if(currentItem.isArchived()) {
holder.archiveRepo.setVisibility(View.VISIBLE);
}
else {
holder.archiveRepo.setVisibility(View.GONE);
}
}
@Override
public int getItemCount() {
return searchedReposList.size();
}
PopupMenu popupMenu = new PopupMenu(context_, v);
popupMenu.inflate(R.menu.repo_dotted_list_menu);
Object menuHelper;
Class[] argTypes;
try {
Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup");
fMenuHelper.setAccessible(true);
menuHelper = fMenuHelper.get(popupMenu);
argTypes = new Class[] { boolean.class };
menuHelper.getClass().getDeclaredMethod("setForceShowIcon",
argTypes).invoke(menuHelper, true);
} catch (Exception e) {
popupMenu.show();
return;
}
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.repoStargazers:
Intent intent = new Intent(context, RepoStargazersActivity.class);
intent.putExtra("repoFullNameForStars", fullName.getText());
context.startActivity(intent);
break;
case R.id.repoWatchers:
Intent intentW = new Intent(context, RepoWatchersActivity.class);
intentW.putExtra("repoFullNameForWatchers", fullName.getText());
context.startActivity(intentW);
break;
case R.id.repoOpenInBrowser:
Intent intentOpenInBrowser = new Intent(context, OpenRepoInBrowserActivity.class);
intentOpenInBrowser.putExtra("repoFullNameBrowser", fullName.getText());
context.startActivity(intentOpenInBrowser);
break;
}
return false;
}
});
popupMenu.show();
}
});
}
}
@NonNull
@Override
public ExploreRepositoriesAdapter.ReposSearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.repos_list, parent, false);
return new ExploreRepositoriesAdapter.ReposSearchViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull final ExploreRepositoriesAdapter.ReposSearchViewHolder holder, int position) {
final UserRepositories currentItem = searchedReposList.get(position);
holder.mTextView2.setVisibility(View.GONE);
ColorGenerator generator = ColorGenerator.MATERIAL;
int color = generator.getColor(currentItem.getName());
String firstCharacter = String.valueOf(currentItem.getName().charAt(0));
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.useFont(Typeface.DEFAULT)
.fontSize(18)
.toUpperCase()
.width(28)
.height(28)
.endConfig()
.buildRoundRect(firstCharacter, color, 3);
if (currentItem.getAvatar_url() != null) {
if (!currentItem.getAvatar_url().equals("")) {
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
} else {
holder.image.setImageDrawable(drawable);
}
}
else {
holder.image.setImageDrawable(drawable);
}
holder.mTextView1.setText(currentItem.getName());
if (!currentItem.getDescription().equals("")) {
holder.mTextView2.setVisibility(View.VISIBLE);
holder.mTextView2.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullname());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock_bold);
}
else {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_public);
}
holder.repoStars.setText(currentItem.getStars_count());
holder.repoForks.setText(currentItem.getForks_count());
holder.repoOpenIssuesCount.setText(currentItem.getOpen_issues_count());
}
@Override
public int getItemCount() {
return searchedReposList.size();
}
} }

View File

@ -11,7 +11,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Files; import org.mian.gitnex.models.Files;
import java.util.ArrayList; import java.util.ArrayList;
@ -37,38 +36,35 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
class FilesViewHolder extends RecyclerView.ViewHolder { class FilesViewHolder extends RecyclerView.ViewHolder {
private ImageView fileTypeImage; private ImageView fileTypeImage;
private ImageView dirTypeImage;
private ImageView unknownTypeImage;
private TextView fileName; private TextView fileName;
private TextView fileType; private TextView fileType;
private TextView fileInfo;
private FilesViewHolder(View itemView) { private FilesViewHolder(View itemView) {
super(itemView); super(itemView);
fileName = itemView.findViewById(R.id.fileName); fileName = itemView.findViewById(R.id.fileName);
fileTypeImage = itemView.findViewById(R.id.fileImage); fileTypeImage = itemView.findViewById(R.id.fileImage);
dirTypeImage = itemView.findViewById(R.id.dirImage);
unknownTypeImage = itemView.findViewById(R.id.unknownImage);
fileType = itemView.findViewById(R.id.fileType); fileType = itemView.findViewById(R.id.fileType);
fileInfo = itemView.findViewById(R.id.fileInfo);
//ImageView filesDropdownMenu = itemView.findViewById(R.id.filesDropdownMenu); //ImageView filesDropdownMenu = itemView.findViewById(R.id.filesDropdownMenu);
fileName.setOnClickListener(v -> { fileName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext(); Context context = v.getContext();
if(fileType.getText().toString().equals("file")) { if(fileType.getText().toString().equals("file")) {
filesListener.onClickFile(fileName.getText().toString()); filesListener.onClickFile(fileName.getText().toString());
} }
else if(fileType.getText().toString().equals("dir")) { else if(fileType.getText().toString().equals("dir")) {
filesListener.onClickDir(fileName.getText().toString()); filesListener.onClickDir(fileName.getText().toString());
} }
else { else {
Toasty.warning(context, context.getString(R.string.filesGenericError)); Toasty.info(context, context.getString(R.string.filesGenericError));
} }
}
}); });
@ -148,7 +144,7 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
@NonNull @NonNull
@Override @Override
public FilesAdapter.FilesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public FilesAdapter.FilesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_files, parent, false); View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.files_list, parent, false);
return new FilesAdapter.FilesViewHolder(v); return new FilesAdapter.FilesViewHolder(v);
} }
@ -161,22 +157,13 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
holder.fileName.setText(currentItem.getName()); holder.fileName.setText(currentItem.getName());
if(currentItem.getType().equals("file")) { if(currentItem.getType().equals("file")) {
holder.fileTypeImage.setVisibility(View.VISIBLE); holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_file_new));
holder.dirTypeImage.setVisibility(View.GONE);
holder.unknownTypeImage.setVisibility(View.GONE);
holder.fileInfo.setVisibility(View.VISIBLE);
holder.fileInfo.setText(AppUtil.formatFileSizeInDetail(currentItem.getSize()));
} }
else if(currentItem.getType().equals("dir")) { else if(currentItem.getType().equals("dir")) {
holder.dirTypeImage.setVisibility(View.VISIBLE); holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_folder_24));
holder.unknownTypeImage.setVisibility(View.GONE);
holder.fileTypeImage.setVisibility(View.GONE);
holder.fileInfo.setVisibility(View.GONE);
} }
else { else {
holder.unknownTypeImage.setVisibility(View.VISIBLE); holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_question_mark_24));
holder.dirTypeImage.setVisibility(View.GONE);
holder.fileTypeImage.setVisibility(View.GONE);
} }
} }

View File

@ -1,267 +1,138 @@
package org.mian.gitnex.adapters; package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.util.TypedValue;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.BaseAdapter; import android.widget.HorizontalScrollView;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.helpers.DiffTextView;
import org.mian.gitnex.models.FileDiffView; import org.mian.gitnex.models.FileDiffView;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
/** /**
* Author opyale * Author M M Arif
*/ */
public class FilesDiffAdapter extends BaseAdapter { public class FilesDiffAdapter extends RecyclerView.Adapter<FilesDiffAdapter.FilesDiffViewHolder> {
private static Map<Long, View> selectedViews; private List<FileDiffView> dataList;
private static final int MAXIMUM_LINES = 5000; private Context ctx;
private static int COLOR_ADDED; static class FilesDiffViewHolder extends RecyclerView.ViewHolder {
private static int COLOR_REMOVED;
private static int COLOR_NORMAL;
private static int COLOR_SELECTED;
private static int COLOR_FONT;
private Context context; private TextView fileContents;
private List<FileDiffView> fileDiffViews; private TextView fileName;
private TextView fileInfo;
private ImageView fileImage;
private HorizontalScrollView fileContentsView;
private LinearLayout allLines;
public FilesDiffAdapter(Context context, List<FileDiffView> fileDiffViews) { private FilesDiffViewHolder(View itemView) {
super(itemView);
this.context = context; fileContents = itemView.findViewById(R.id.fileContents);
this.fileDiffViews = fileDiffViews; fileName = itemView.findViewById(R.id.fileName);
fileInfo = itemView.findViewById(R.id.fileInfo);
fileImage = itemView.findViewById(R.id.fileImage);
fileContentsView = itemView.findViewById(R.id.fileContentsView);
allLines = itemView.findViewById(R.id.allLinesLayout);
selectedViews = new ConcurrentSkipListMap<>(); }
}
COLOR_ADDED = getColorFromAttribute(R.attr.diffAddedColor); public FilesDiffAdapter(List<FileDiffView> dataListMain, Context ctx) {
COLOR_REMOVED = getColorFromAttribute(R.attr.diffRemovedColor); this.dataList = dataListMain;
COLOR_NORMAL = getColorFromAttribute(R.attr.primaryBackgroundColor); this.ctx = ctx;
COLOR_SELECTED = getColorFromAttribute(R.attr.diffSelectedColor); }
COLOR_FONT = getColorFromAttribute(R.attr.inputTextColor);
} @NonNull
@Override
public FilesDiffAdapter.FilesDiffViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.files_diffs_list, parent, false);
return new FilesDiffAdapter.FilesDiffViewHolder(v);
}
@Override @Override
public int getCount() { public void onBindViewHolder(@NonNull FilesDiffViewHolder holder, int position) {
return fileDiffViews.size(); FileDiffView data = dataList.get(position);
}
@Override if(data.isFileType()) {
public Object getItem(int position) {
return fileDiffViews.get(position); holder.fileName.setText(data.getFileName());
}
@Override holder.fileInfo.setVisibility(View.GONE);
public long getItemId(int position) {
return position; //byte[] imageData = Base64.decode(data.getFileContents(), Base64.DEFAULT);
} //Drawable imageDrawable = new BitmapDrawable(ctx.getResources(), BitmapFactory.decodeByteArray(imageData, 0, imageData.length));
//holder.fileImage.setImageDrawable(imageDrawable);
holder.fileContentsView.setVisibility(View.GONE);
@SuppressLint({"ViewHolder", "InflateParams"}) }
@Override else {
public View getView(int position, View convertView, ViewGroup parent) {
convertView = LayoutInflater.from(context).inflate(R.layout.list_files_diffs, null, false); String[] splitData = data.getFileContents().split("\\R");
TextView headerFileName = convertView.findViewById(R.id.headerFileName); for (String eachSplit : splitData) {
TextView headerFileInfo = convertView.findViewById(R.id.headerFileInfo);
ImageView footerImage = convertView.findViewById(R.id.footerImage);
LinearLayout diffStats = convertView.findViewById(R.id.diff_stats);
LinearLayout diffLines = convertView.findViewById(R.id.diffLines);
FileDiffView data = (FileDiffView) getItem(position); TextView textLine = new TextView(ctx);
headerFileName.setText(data.getFileName()); textLine.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
if(data.isFileBinary()) { if (eachSplit.startsWith("+")) {
diffStats.setVisibility(View.GONE); textLine.setText(eachSplit);
diffLines.addView(getMessageView(context.getResources().getString(R.string.binaryFileError))); holder.allLines.addView(textLine);
} textLine.setTextColor(ctx.getResources().getColor(R.color.colorPrimary));
else { textLine.setPadding(5, 5, 5, 5);
textLine.setBackgroundColor(ctx.getResources().getColor(R.color.diffAddedColor));
diffStats.setVisibility(View.VISIBLE); }
headerFileInfo.setText(data.getFileInfo()); else if (eachSplit.startsWith("-")) {
String[] codeLines = getLines(data.toString()); textLine.setText(eachSplit);
holder.allLines.addView(textLine);
if(MAXIMUM_LINES > codeLines.length) { textLine.setTextColor(ctx.getResources().getColor(R.color.colorPrimary));
textLine.setPadding(5, 5, 5, 5);
textLine.setBackgroundColor(ctx.getResources().getColor(R.color.diffRemovedColor));
for(int l=0; l<codeLines.length; l++) { }
else {
if(codeLines[l].length() > 0) { if(eachSplit.length() > 0) {
textLine.setText(eachSplit);
holder.allLines.addView(textLine);
int uniquePosition = l + (position * MAXIMUM_LINES); textLine.setTextColor(ctx.getResources().getColor(R.color.colorPrimary));
textLine.setPadding(5, 5, 5, 5);
textLine.setBackgroundColor(ctx.getResources().getColor(R.color.white));
}
DiffTextView diffTextView = new DiffTextView(context); }
diffTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15); }
diffTextView.setPadding(15, 2, 15, 2);
diffTextView.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/sourcecodeproregular.ttf"));
diffTextView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
diffTextView.setPosition(uniquePosition);
boolean isSelected = false; holder.fileName.setText(data.getFileName());
if(!data.getFileInfo().equals("")) {
holder.fileInfo.setText(ctx.getResources().getString(R.string.fileDiffInfoChanges, data.getFileInfo()));
}
else {
holder.fileInfo.setVisibility(View.GONE);
}
for(View view : selectedViews.values()) { }
if(((DiffTextView) view).getPosition() == uniquePosition) { }
diffTextView.setBackgroundColor(COLOR_SELECTED); @Override
isSelected = true; public int getItemCount() {
break; return dataList.size();
}
} }
}
if(codeLines[l].startsWith("+")) {
diffTextView.setText(codeLines[l]);
diffTextView.setTextColor(COLOR_FONT);
if(!isSelected) {
diffTextView.setInitialBackgroundColor(COLOR_ADDED);
}
}
else if(codeLines[l].startsWith("-")) {
diffTextView.setText(codeLines[l]);
diffTextView.setTextColor(COLOR_FONT);
if(!isSelected) {
diffTextView.setInitialBackgroundColor(COLOR_REMOVED);
}
}
else {
diffTextView.setText(codeLines[l]);
diffTextView.setTextColor(COLOR_FONT);
if(!isSelected) {
diffTextView.setInitialBackgroundColor(COLOR_NORMAL);
}
}
diffTextView.setOnClickListener(v -> {
if(((DiffTextView) v).getCurrentBackgroundColor() != COLOR_SELECTED) {
selectedViews.put(((DiffTextView) v).getPosition(), v);
v.setBackgroundColor(COLOR_SELECTED);
}
else {
selectedViews.remove(((DiffTextView) v).getPosition());
v.setBackgroundColor(((DiffTextView) v).getInitialBackgroundColor());
}
});
diffTextView.setOnLongClickListener(v -> {
if(((DiffTextView) v).getCurrentBackgroundColor() == COLOR_SELECTED) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("```\n");
for(View view : selectedViews.values()) {
stringBuilder.append(((DiffTextView) view).getText());
stringBuilder.append("\n");
}
stringBuilder.append("```\n\n");
selectedViews.clear();
Intent intent = new Intent(context, ReplyToIssueActivity.class);
intent.putExtra("commentBody", stringBuilder.toString());
intent.putExtra("cursorToEnd", true);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
return true;
});
diffLines.addView(diffTextView);
}
}
}
else {
diffLines.addView(getMessageView(context.getResources().getString(R.string.fileTooLarge)));
}
}
return convertView;
}
private TextView getMessageView(String message) {
TextView textView = new TextView(context);
textView.setTextColor(COLOR_FONT);
textView.setBackgroundColor(COLOR_NORMAL);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
textView.setPadding(15, 15, 15, 15);
textView.setTypeface(Typeface.DEFAULT);
textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
textView.setText(message);
return textView;
}
private String[] getLines(String content) {
return content.split("\\R");
}
private int getColorFromAttribute(int resid) {
TypedValue typedValue = new TypedValue();
context.getTheme().resolveAttribute(resid, typedValue, true);
return typedValue.data;
}
}

View File

@ -1,40 +1,41 @@
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;
import android.net.Uri; import android.net.Uri;
import android.text.Spanned; import android.text.Spanned;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import com.squareup.picasso.Picasso;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.gson.JsonElement;
import com.vdurmont.emoji.EmojiParser; import com.vdurmont.emoji.EmojiParser;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity; import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper; import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UserMentions; import org.mian.gitnex.helpers.UserMentions;
import org.mian.gitnex.models.IssueComments; import org.mian.gitnex.models.IssueComments;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.helpers.ClickListener;
import org.ocpsoft.prettytime.PrettyTime;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
import 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;
@ -43,6 +44,7 @@ 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;
@ -50,8 +52,6 @@ import io.noties.markwon.image.SchemeHandler;
import io.noties.markwon.image.gif.GifMediaDecoder; import io.noties.markwon.image.gif.GifMediaDecoder;
import io.noties.markwon.image.svg.SvgMediaDecoder; import io.noties.markwon.image.svg.SvgMediaDecoder;
import io.noties.markwon.linkify.LinkifyPlugin; import io.noties.markwon.linkify.LinkifyPlugin;
import retrofit2.Call;
import retrofit2.Callback;
/** /**
* Author M M Arif * Author M M Arif
@ -59,357 +59,232 @@ import retrofit2.Callback;
public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdapter.IssueCommentViewHolder> { public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdapter.IssueCommentViewHolder> {
private List<IssueComments> issuesComments; private List<IssueComments> issuesComments;
private Context mCtx; private Context mCtx;
public IssueCommentsAdapter(Context mCtx, List<IssueComments> issuesCommentsMain) { static class IssueCommentViewHolder extends RecyclerView.ViewHolder {
this.mCtx = mCtx; private TextView issueNumber;
this.issuesComments = issuesCommentsMain; private TextView commendId;
private ImageView issueCommenterAvatar;
} private TextView issueComment;
private TextView issueCommentDate;
class IssueCommentViewHolder extends RecyclerView.ViewHolder { private ImageView commentsOptionsMenu;
private TextView commendBodyRaw;
private TextView issueNumber; private TextView commentModified;
private TextView commendId;
private ImageView issueCommenterAvatar; private IssueCommentViewHolder(View itemView) {
private TextView issueComment; super(itemView);
private TextView issueCommentDate;
private TextView commendBodyRaw; issueNumber = itemView.findViewById(R.id.issueNumber);
private TextView commentModified; commendId = itemView.findViewById(R.id.commendId);
private TextView commenterUsername; issueCommenterAvatar = itemView.findViewById(R.id.issueCommenterAvatar);
private TextView htmlUrl; issueComment = itemView.findViewById(R.id.issueComment);
issueCommentDate = itemView.findViewById(R.id.issueCommentDate);
private IssueCommentViewHolder(View itemView) { commentsOptionsMenu = itemView.findViewById(R.id.commentsOptionsMenu);
commendBodyRaw = itemView.findViewById(R.id.commendBodyRaw);
super(itemView); commentModified = itemView.findViewById(R.id.commentModified);
issueNumber = itemView.findViewById(R.id.issueNumber); commentsOptionsMenu.setOnClickListener(new View.OnClickListener() {
commendId = itemView.findViewById(R.id.commendId); @Override
issueCommenterAvatar = itemView.findViewById(R.id.issueCommenterAvatar); public void onClick(View v) {
issueComment = itemView.findViewById(R.id.issueComment);
issueCommentDate = itemView.findViewById(R.id.issueCommentDate); final Context context = v.getContext();
ImageView commentsOptionsMenu = itemView.findViewById(R.id.commentsOptionsMenu); Context context_ = new ContextThemeWrapper(context, R.style.popupMenuStyle);
commendBodyRaw = itemView.findViewById(R.id.commendBodyRaw);
commentModified = itemView.findViewById(R.id.commentModified); PopupMenu popupMenu = new PopupMenu(context_, v);
commenterUsername = itemView.findViewById(R.id.commenterUsername); popupMenu.inflate(R.menu.issue_comment_menu);
htmlUrl = itemView.findViewById(R.id.htmlUrl);
Object menuHelper;
commentsOptionsMenu.setOnClickListener(v -> { Class[] argTypes;
try {
final Context ctx = v.getContext();
final TinyDB tinyDb = new TinyDB(ctx); Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup");
final String loginUid = tinyDb.getString("loginUid"); fMenuHelper.setAccessible(true);
menuHelper = fMenuHelper.get(popupMenu);
@SuppressLint("InflateParams") View view = LayoutInflater.from(ctx).inflate(R.layout.bottom_sheet_issue_comments, null); argTypes = new Class[] { boolean.class };
menuHelper.getClass().getDeclaredMethod("setForceShowIcon",
TextView commentMenuEdit = view.findViewById(R.id.commentMenuEdit); argTypes).invoke(menuHelper, true);
TextView commentShare = view.findViewById(R.id.issueCommentShare);
TextView commentMenuQuote = view.findViewById(R.id.commentMenuQuote); } catch (Exception e) {
TextView commentMenuCopy = view.findViewById(R.id.commentMenuCopy);
TextView commentMenuDelete = view.findViewById(R.id.commentMenuDelete); popupMenu.show();
TextView issueCommentCopyUrl = view.findViewById(R.id.issueCommentCopyUrl); return;
if(!loginUid.contentEquals(commenterUsername.getText())) { }
commentMenuEdit.setVisibility(View.GONE);
commentMenuDelete.setVisibility(View.GONE); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
} @Override
public boolean onMenuItemClick(MenuItem item) {
if(issueComment.getText().toString().isEmpty()) { switch (item.getItemId()) {
commentMenuCopy.setVisibility(View.GONE); case R.id.commentMenuEdit:
}
Intent intent = new Intent(context, ReplyToIssueActivity.class);
BottomSheetDialog dialog = new BottomSheetDialog(ctx); intent.putExtra("commentId", commendId.getText());
dialog.setContentView(view); intent.putExtra("commentAction", "edit");
dialog.show(); intent.putExtra("commentBody", commendBodyRaw.getText());
context.startActivity(intent);
commentMenuEdit.setOnClickListener(ediComment -> { break;
Intent intent = new Intent(ctx, ReplyToIssueActivity.class); case R.id.commentMenuDelete:
intent.putExtra("commentId", commendId.getText());
intent.putExtra("commentAction", "edit"); break;
intent.putExtra("commentBody", commendBodyRaw.getText());
ctx.startActivity(intent); }
dialog.dismiss(); return false;
}
}); });
commentShare.setOnClickListener(ediComment -> { popupMenu.show();
// get comment Url }
CharSequence commentUrl = htmlUrl.getText(); });
// share issue comment }
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); }
sharingIntent.setType("text/plain");
String intentHeader = tinyDb.getString("issueNumber") + ctx.getResources().getString(R.string.hash) + "issuecomment-" + commendId.getText() + " " + tinyDb.getString("issueTitle"); public IssueCommentsAdapter(Context mCtx, List<IssueComments> issuesCommentsMain) {
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, intentHeader); this.mCtx = mCtx;
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, commentUrl); this.issuesComments = issuesCommentsMain;
ctx.startActivity(Intent.createChooser(sharingIntent, intentHeader)); }
dialog.dismiss(); @NonNull
@Override
}); public IssueCommentsAdapter.IssueCommentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.issue_comments, parent, false);
issueCommentCopyUrl.setOnClickListener(ediComment -> { return new IssueCommentsAdapter.IssueCommentViewHolder(v);
}
// comment Url
CharSequence commentUrl = htmlUrl.getText(); @SuppressLint("SetTextI18n")
@Override
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE); public void onBindViewHolder(@NonNull IssueCommentsAdapter.IssueCommentViewHolder holder, int position) {
assert clipboard != null;
final TinyDB tinyDb = new TinyDB(mCtx);
ClipData clip = ClipData.newPlainText(commentUrl, commentUrl); final String locale = tinyDb.getString("locale");
clipboard.setPrimaryClip(clip); final String timeFormat = tinyDb.getString("dateFormat");
final String loginUid = tinyDb.getString("loginUid");
dialog.dismiss();
Toasty.success(ctx, ctx.getString(R.string.copyIssueUrlToastMsg)); IssueComments currentItem = issuesComments.get(position);
}); if(!loginUid.equals(currentItem.getUser().getUsername())) {
holder.commentsOptionsMenu.setVisibility(View.INVISIBLE);
commentMenuQuote.setOnClickListener(v1 -> { }
holder.commendId.setText(String.valueOf(currentItem.getId()));
StringBuilder stringBuilder = new StringBuilder(); holder.commendBodyRaw.setText(currentItem.getBody());
String commenterName = commenterUsername.getText().toString();
if (!currentItem.getUser().getFull_name().equals("")) {
if(!commenterName.equals(tinyDb.getString("userLogin"))) { holder.issueCommenterAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCommenter) + currentItem.getUser().getFull_name(), mCtx));
} else {
stringBuilder.append("@").append(commenterName).append("\n\n"); holder.issueCommenterAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCommenter) + currentItem.getUser().getLogin(), mCtx));
} }
String[] lines = commendBodyRaw.getText().toString().split("\\R"); if (currentItem.getUser().getAvatar_url() != null) {
Picasso.get().load(currentItem.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.issueCommenterAvatar);
for(String line : lines) { } else {
Picasso.get().load(currentItem.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.issueCommenterAvatar);
stringBuilder.append(">").append(line).append("\n"); }
}
String cleanIssueComments = currentItem.getBody().trim();
stringBuilder.append("\n");
final Markwon markwon = Markwon.builder(Objects.requireNonNull(mCtx))
Intent intent = new Intent(ctx, ReplyToIssueActivity.class); .usePlugin(CorePlugin.create())
intent.putExtra("commentBody", stringBuilder.toString()); .usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
intent.putExtra("cursorToEnd", true); @Override
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); public void configureImages(@NonNull ImagesPlugin plugin) {
plugin.addSchemeHandler(new SchemeHandler() {
dialog.dismiss(); @NonNull
ctx.startActivity(intent); @Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
});
final int resourceId = mCtx.getResources().getIdentifier(
commentMenuCopy.setOnClickListener(view1 -> { raw.substring("drawable://".length()),
"drawable",
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(ctx).getSystemService(Context.CLIPBOARD_SERVICE); mCtx.getPackageName());
assert clipboard != null;
final Drawable drawable = mCtx.getDrawable(resourceId);
ClipData clip = ClipData.newPlainText("Comment on issue #" + issueNumber.getText().toString(), issueComment.getText().toString());
clipboard.setPrimaryClip(clip); assert drawable != null;
return ImageItem.withResult(drawable);
dialog.dismiss(); }
Toasty.success(ctx, ctx.getString(R.string.copyIssueCommentToastMsg));
@NonNull
}); @Override
public Collection<String> supportedSchemes() {
commentMenuDelete.setOnClickListener(deleteComment -> { return Collections.singleton("drawable");
}
deleteIssueComment(ctx, Integer.parseInt(commendId.getText().toString()), getAdapterPosition()); });
dialog.dismiss(); plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
@Nullable
}); @Override
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
}); return null;
}
} });
plugin.addMediaDecoder(GifMediaDecoder.create(false));
} plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
private void updateAdapter(int position) { plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
issuesComments.remove(position); }
notifyItemRemoved(position); }))
notifyItemRangeChanged(position, issuesComments.size()); .usePlugin(new AbstractMarkwonPlugin() {
@Override
} public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder
private void deleteIssueComment(final Context ctx, final int commentId, int position) { .codeTextColor(tinyDb.getInt("codeBlockColor"))
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
final TinyDB tinyDb = new TinyDB(ctx); .linkColor(mCtx.getResources().getColor(R.color.lightBlue));
final String instanceUrl = tinyDb.getString("instanceUrl"); }
final String loginUid = tinyDb.getString("loginUid"); })
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); .usePlugin(TablePlugin.create(mCtx))
String[] repoFullName = tinyDb.getString("repoFullName").split("/"); .usePlugin(TaskListPlugin.create(mCtx))
if (repoFullName.length != 2) { .usePlugin(HtmlPlugin.create())
return; .usePlugin(StrikethroughPlugin.create())
} .usePlugin(LinkifyPlugin.create())
final String repoOwner = repoFullName[0]; .build();
final String repoName = repoFullName[1];
Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueComments));
Call<JsonElement> call; markwon.setParsedMarkdown(holder.issueComment, UserMentions.UserMentionsFunc(mCtx, bodyWithMD, cleanIssueComments));
call = RetrofitClient String edited;
.getInstance(instanceUrl, ctx)
.getApiInterface() if(!currentItem.getUpdated_at().equals(currentItem.getCreated_at())) {
.deleteComment(instanceToken, repoOwner, repoName, commentId); edited = mCtx.getResources().getString(R.string.colorfulBulletSpan) + mCtx.getResources().getString(R.string.modifiedText);
holder.commentModified.setVisibility(View.VISIBLE);
call.enqueue(new Callback<JsonElement>() { holder.commentModified.setText(edited);
holder.commentModified.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getUpdated_at()), mCtx));
@Override }
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) { else {
holder.commentModified.setVisibility(View.INVISIBLE);
if(response.code() == 204) { }
updateAdapter(position); switch (timeFormat) {
Toasty.success(ctx, ctx.getResources().getString(R.string.deleteCommentSuccess)); case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
} String createdTime = prettyTime.format(currentItem.getCreated_at());
else if(response.code() == 401) { holder.issueCommentDate.setText(createdTime);
holder.issueCommentDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getCreated_at()), mCtx));
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle), break;
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage), }
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), case "normal": {
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + mCtx.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(currentItem.getCreated_at());
} holder.issueCommentDate.setText(createdTime);
else if(response.code() == 403) { break;
}
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + mCtx.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
} String createdTime = formatter.format(currentItem.getCreated_at());
else if(response.code() == 404) { holder.issueCommentDate.setText(createdTime);
break;
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)); }
}
}
else { }
Toasty.error(ctx, ctx.getString(R.string.genericError)); @Override
public int getItemCount() {
} return issuesComments.size();
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
}
@NonNull
@Override
public IssueCommentsAdapter.IssueCommentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_issue_comments, parent, false);
return new IssueCommentsAdapter.IssueCommentViewHolder(v);
}
@SuppressLint("SetTextI18n")
@Override
public void onBindViewHolder(@NonNull IssueCommentsAdapter.IssueCommentViewHolder holder, int position) {
final TinyDB tinyDb = new TinyDB(mCtx);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
IssueComments currentItem = issuesComments.get(position);
holder.htmlUrl.setText(currentItem.getHtml_url());
holder.commenterUsername.setText(currentItem.getUser().getUsername());
holder.commendId.setText(String.valueOf(currentItem.getId()));
holder.commendBodyRaw.setText(currentItem.getBody());
if(!currentItem.getUser().getFull_name().equals("")) {
holder.issueCommenterAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCommenter) + currentItem.getUser().getFull_name(), mCtx));
}
else {
holder.issueCommenterAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCommenter) + currentItem.getUser().getLogin(), mCtx));
}
PicassoService.getInstance(mCtx).get().load(currentItem.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.issueCommenterAvatar);
String cleanIssueComments = currentItem.getBody().trim();
final Markwon markwon = Markwon.builder(Objects.requireNonNull(mCtx)).usePlugin(CorePlugin.create()).usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
@Override
public void configureImages(@NonNull ImagesPlugin plugin) {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = mCtx.getResources().getIdentifier(raw.substring("drawable://".length()), "drawable", mCtx.getPackageName());
final Drawable drawable = mCtx.getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(drawable -> null);
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}
})).usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder.codeTextColor(tinyDb.getInt("codeBlockColor")).codeBackgroundColor(tinyDb.getInt("codeBlockBackground")).linkColor(mCtx.getResources().getColor(R.color.lightBlue));
}
}).usePlugin(TablePlugin.create(mCtx)).usePlugin(TaskListPlugin.create(mCtx)).usePlugin(HtmlPlugin.create()).usePlugin(StrikethroughPlugin.create()).usePlugin(LinkifyPlugin.create()).build();
Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueComments));
markwon.setParsedMarkdown(holder.issueComment, UserMentions.UserMentionsFunc(mCtx, bodyWithMD, cleanIssueComments));
String edited;
if(!currentItem.getUpdated_at().equals(currentItem.getCreated_at())) {
edited = mCtx.getResources().getString(R.string.colorfulBulletSpan) + mCtx.getResources().getString(R.string.modifiedText);
holder.commentModified.setVisibility(View.VISIBLE);
holder.commentModified.setText(edited);
holder.commentModified.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getUpdated_at()), mCtx));
}
else {
holder.commentModified.setVisibility(View.INVISIBLE);
}
holder.issueCommentDate.setText(TimeHelper.formatTime(currentItem.getCreated_at(), new Locale(locale), timeFormat, mCtx));
if(timeFormat.equals("pretty")) {
holder.issueCommentDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getCreated_at()), mCtx));
}
}
@Override
public int getItemCount() {
return issuesComments.size();
}
} }

View File

@ -7,230 +7,285 @@ import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import com.squareup.picasso.Picasso;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity; import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.ClickListener; import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper; import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Issues; import org.mian.gitnex.models.Issues;
import org.mian.gitnex.util.TinyDB;
import org.ocpsoft.prettytime.PrettyTime; import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
/** /**
* Author M M Arif * Author M M Arif
*/ */
public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {
private Context context; private Context context;
private final int TYPE_LOAD = 0; private final int TYPE_LOAD = 0;
private List<Issues> issuesList; private List<Issues> issuesList;
private OnLoadMoreListener loadMoreListener; private List<Issues> issuesListFull;
private boolean isLoading = false, isMoreDataAvailable = true; private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public IssuesAdapter(Context context, List<Issues> issuesListMain) { public IssuesAdapter(Context context, List<Issues> issuesListMain) {
this.context = context; this.context = context;
this.issuesList = issuesListMain; this.issuesList = issuesListMain;
issuesListFull = new ArrayList<>(issuesList);
} }
@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 IssuesHolder(inflater.inflate(R.layout.list_issues, parent, false)); return new IssuesHolder(inflater.inflate(R.layout.repo_detail_issues_list, parent,false));
} }
else { else {
return new LoadHolder(inflater.inflate(R.layout.row_load, parent, false)); return new LoadHolder(inflater.inflate(R.layout.row_load,parent,false));
} }
} }
@Override @Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) { if(position >= getItemCount()-1 && isMoreDataAvailable && !isLoading && loadMoreListener!=null) {
isLoading = true; isLoading = true;
loadMoreListener.onLoadMore(); loadMoreListener.onLoadMore();
} }
if(getItemViewType(position) == TYPE_LOAD) { if(getItemViewType(position) == TYPE_LOAD) {
((IssuesHolder) holder).bindData(issuesList.get(position)); ((IssuesHolder)holder).bindData(issuesList.get(position));
} }
} }
@Override @Override
public int getItemViewType(int position) { public int getItemViewType(int position) {
if(issuesList.get(position).getTitle() != null) { if(issuesList.get(position).getTitle() != null) {
return TYPE_LOAD; return TYPE_LOAD;
} }
else { else {
return 1; return 1;
} }
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return issuesList.size(); return issuesList.size();
} }
class IssuesHolder extends RecyclerView.ViewHolder { class IssuesHolder extends RecyclerView.ViewHolder {
private TextView issueNumber; private TextView issueNumber;
private ImageView issueAssigneeAvatar; private ImageView issueAssigneeAvatar;
private TextView issueTitle; private TextView issueTitle;
private TextView issueCreatedTime; private TextView issueCreatedTime;
private TextView issueCommentsCount; private TextView issueCommentsCount;
private RelativeLayout relativeLayoutFrame;
IssuesHolder(View itemView) { IssuesHolder(View itemView) {
super(itemView); super(itemView);
issueNumber = itemView.findViewById(R.id.issueNumber); issueNumber = itemView.findViewById(R.id.issueNumber);
issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar); issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
issueTitle = itemView.findViewById(R.id.issueTitle); issueTitle = itemView.findViewById(R.id.issueTitle);
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount); issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount); LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount);
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime); issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
relativeLayoutFrame = itemView.findViewById(R.id.relativeLayoutFrame);
issueTitle.setOnClickListener(v -> { issueTitle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext(); Context context = v.getContext();
//Log.i("issueNumber", issueNumber.getText().toString());
Intent intent = new Intent(context, IssueDetailActivity.class); Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText()); intent.putExtra("issueNumber", issueNumber.getText());
TinyDB tinyDb = new TinyDB(context); TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString()); tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "Issue"); tinyDb.putString("issueType", "issue");
context.startActivity(intent); context.startActivity(intent);
}); }
frameCommentsCount.setOnClickListener(v -> { });
frameCommentsCount.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext(); Context context = v.getContext();
//Log.i("issueNumber", issueNumber.getText().toString());
Intent intent = new Intent(context, IssueDetailActivity.class); Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText()); intent.putExtra("issueNumber", issueNumber.getText());
TinyDB tinyDb = new TinyDB(context); TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString()); tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueType", "Issue"); tinyDb.putString("issueType", "issue");
context.startActivity(intent); context.startActivity(intent);
}); }
});
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
void bindData(Issues issuesModel) { void bindData(Issues issuesModel){
final TinyDB tinyDb = new TinyDB(context); final TinyDB tinyDb = new TinyDB(context);
final String locale = tinyDb.getString("locale"); final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat"); final String timeFormat = tinyDb.getString("dateFormat");
if(!issuesModel.getUser().getFull_name().equals("")) { /*if(issuesModel.getPull_request() != null) {
issueAssigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueCreator) + issuesModel.getUser().getFull_name(), context)); if (!issuesModel.getPull_request().isMerged()) {
} relativeLayoutFrame.setVisibility(View.GONE);
else { relativeLayoutFrame.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
issueAssigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueCreator) + issuesModel.getUser().getLogin(), context)); }
} }*/
PicassoService.getInstance(context).get().load(issuesModel.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar); if (!issuesModel.getUser().getFull_name().equals("")) {
issueAssigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueCreator) + issuesModel.getUser().getFull_name(), context));
} else {
issueAssigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.issueCreator) + issuesModel.getUser().getLogin(), context));
}
String issueNumber_ = "<font color='" + context.getResources().getColor(R.color.lightGray) + "'>" + context.getResources().getString(R.string.hash) + issuesModel.getNumber() + "</font>"; if (issuesModel.getUser().getAvatar_url() != null) {
issueTitle.setText(Html.fromHtml(issueNumber_ + " " + issuesModel.getTitle())); Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar);
} else {
Picasso.get().load(issuesModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar);
}
issueNumber.setText(String.valueOf(issuesModel.getNumber())); String issueNumber_ = "<font color='" + context.getResources().getColor(R.color.lightGray) + "'>" + context.getResources().getString(R.string.hash) + issuesModel.getNumber() + "</font>";
issueCommentsCount.setText(String.valueOf(issuesModel.getComments())); issueTitle.setText(Html.fromHtml(issueNumber_ + " " + issuesModel.getTitle()));
switch(timeFormat) { issueNumber.setText(String.valueOf(issuesModel.getNumber()));
case "pretty": { issueCommentsCount.setText(String.valueOf(issuesModel.getComments()));
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(issuesModel.getCreated_at()), context));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
break;
}
}
} switch (timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(issuesModel.getCreated_at()), context));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
break;
}
}
} }
static class LoadHolder extends RecyclerView.ViewHolder { }
LoadHolder(View itemView) { static class LoadHolder extends RecyclerView.ViewHolder {
super(itemView); LoadHolder(View itemView) {
} super(itemView);
}
} }
public void setMoreDataAvailable(boolean moreDataAvailable) { public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable; isMoreDataAvailable = moreDataAvailable;
} }
public void notifyDataChanged() { public void notifyDataChanged() {
notifyDataSetChanged(); notifyDataSetChanged();
isLoading = false; isLoading = false;
} }
public interface OnLoadMoreListener { public interface OnLoadMoreListener {
void onLoadMore(); void onLoadMore();
} }
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) { public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener; this.loadMoreListener = loadMoreListener;
} }
public void updateList(List<Issues> list) { @Override
public Filter getFilter() {
return issuesFilter;
}
issuesList = list; private Filter issuesFilter = new Filter() {
notifyDataSetChanged(); @Override
} protected FilterResults performFiltering(CharSequence constraint) {
List<Issues> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(issuesList);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (Issues item : issuesList) {
if (item.getTitle().toLowerCase().contains(filterPattern) || item.getBody().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
issuesList.clear();
issuesList.addAll((List) results.values);
notifyDataSetChanged();
}
};
} }

View File

@ -1,27 +1,29 @@
package org.mian.gitnex.adapters; package org.mian.gitnex.adapters;
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.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import com.amulyakhare.textdrawable.TextDrawable;
import androidx.cardview.widget.CardView;
import androidx.core.widget.ImageViewCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.mian.gitnex.R; import org.mian.gitnex.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.lang.reflect.Field;
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.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
/** /**
* Author M M Arif * Author M M Arif
@ -38,61 +40,76 @@ 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);
labelView = itemView.findViewById(R.id.labelView); labelsView = itemView.findViewById(R.id.labelsView);
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);
labelColor = itemView.findViewById(R.id.labelColor); labelColor = itemView.findViewById(R.id.labelColor);
labelsOptionsMenu.setOnClickListener(v -> { labelsOptionsMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Context context = v.getContext(); final Context context = v.getContext();
Context context_ = new ContextThemeWrapper(context, R.style.popupMenuStyle);
@SuppressLint("InflateParams") PopupMenu popupMenu = new PopupMenu(context_, v);
View view = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_labels_in_list, null); popupMenu.inflate(R.menu.labels_menu);
TextView labelMenuEdit = view.findViewById(R.id.labelMenuEdit); Object menuHelper;
TextView labelMenuDelete = view.findViewById(R.id.labelMenuDelete); Class[] argTypes;
TextView bottomSheetHeader = view.findViewById(R.id.bottomSheetHeader); try {
bottomSheetHeader.setText(labelTitle.getText()); Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup");
BottomSheetDialog dialog = new BottomSheetDialog(context); fMenuHelper.setAccessible(true);
dialog.setContentView(view); menuHelper = fMenuHelper.get(popupMenu);
dialog.show(); argTypes = new Class[] { boolean.class };
menuHelper.getClass().getDeclaredMethod("setForceShowIcon",
argTypes).invoke(menuHelper, true);
labelMenuEdit.setOnClickListener(editLabel -> { } catch (Exception e) {
Intent intent = new Intent(context, CreateLabelActivity.class); popupMenu.show();
intent.putExtra("labelId", labelId.getText()); return;
intent.putExtra("labelTitle", labelTitle.getText());
intent.putExtra("labelColor", labelColor.getText());
intent.putExtra("labelAction", "edit");
context.startActivity(intent);
dialog.dismiss();
}); }
labelMenuDelete.setOnClickListener(deleteLabel -> { popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.labelMenuEdit:
AlertDialogs.labelDeleteDialog(context, labelTitle.getText().toString(), labelId.getText().toString(), Intent intent = new Intent(context, CreateLabelActivity.class);
context.getResources().getString(R.string.labelDeleteTitle), intent.putExtra("labelId", labelId.getText());
context.getResources().getString(R.string.labelDeleteMessage), intent.putExtra("labelTitle", labelTitle.getText());
context.getResources().getString(R.string.labelDeletePositiveButton), intent.putExtra("labelColor", labelColor.getText());
context.getResources().getString(R.string.labelDeleteNegativeButton)); intent.putExtra("labelAction", "edit");
dialog.dismiss(); context.startActivity(intent);
break;
}); case R.id.labelMenuDelete:
AlertDialogs.labelDeleteDialog(context, labelTitle.getText().toString(), labelId.getText().toString(),
context.getResources().getString(R.string.labelDeleteTitle),
context.getResources().getString(R.string.labelDeleteMessage),
context.getResources().getString(R.string.labelDeletePositiveButton),
context.getResources().getString(R.string.labelDeleteNegativeButton));
break;
}
return false;
}
});
popupMenu.show();
}
}); });
} }
@ -106,7 +123,7 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
@NonNull @NonNull
@Override @Override
public LabelsAdapter.LabelsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public LabelsAdapter.LabelsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_labels, parent, false); View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.labels_list, parent, false);
return new LabelsAdapter.LabelsViewHolder(v); return new LabelsAdapter.LabelsViewHolder(v);
} }
@ -114,6 +131,7 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
public void onBindViewHolder(@NonNull LabelsAdapter.LabelsViewHolder holder, int position) { public void onBindViewHolder(@NonNull LabelsAdapter.LabelsViewHolder holder, int position) {
Labels currentItem = labelsList.get(position); Labels currentItem = labelsList.get(position);
int width = 33;
holder.labelTitle.setText(currentItem.getName()); holder.labelTitle.setText(currentItem.getName());
holder.labelId.setText(String.valueOf(currentItem.getId())); holder.labelId.setText(String.valueOf(currentItem.getId()));
@ -121,15 +139,32 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
String labelColor = currentItem.getColor(); String labelColor = currentItem.getColor();
String labelName = currentItem.getName(); String labelName = currentItem.getName();
int color = Color.parseColor("#" + labelColor); int color = Color.parseColor("#" + labelColor);
int contrastColor = new ColorInverter().getContrastColor(color);
ImageViewCompat.setImageTintList(holder.labelIcon, ColorStateList.valueOf(contrastColor)); TextDrawable drawable = TextDrawable.builder()
.beginConfig()
//.useFont(Typeface.DEFAULT)
.bold()
.textColor(new ColorInverter().getContrastColor(color))
.fontSize(36)
.width(LabelWidthCalculator.customWidth(getMaxLabelLength()))
.height(60)
.endConfig()
.buildRoundRect(labelName, color, 8);
holder.labelsView.setImageDrawable(drawable);
holder.labelName.setTextColor(contrastColor); }
holder.labelName.setText(labelName);
holder.labelView.setCardBackgroundColor(color); private int getMaxLabelLength() {
for(int i = 0; i < labelsList.size(); i++) {
Labels labelItem = labelsList.get(i);
labelsArray.add(labelItem.getName().length());
}
return Collections.max(labelsArray);
} }
@ -138,4 +173,4 @@ public class LabelsAdapter extends RecyclerView.Adapter<LabelsAdapter.LabelsView
return labelsList.size(); return labelsList.size();
} }
} }

View File

@ -10,8 +10,8 @@ import android.widget.Filter;
import android.widget.Filterable; import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo; import org.mian.gitnex.models.UserInfo;
import java.util.ArrayList; import java.util.ArrayList;
@ -67,7 +67,7 @@ public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
MembersByOrgAdapter.ViewHolder viewHolder = null; MembersByOrgAdapter.ViewHolder viewHolder = null;
if (finalView == null) { if (finalView == null) {
finalView = LayoutInflater.from(mCtx).inflate(R.layout.list_members_by_org, null); finalView = LayoutInflater.from(mCtx).inflate(R.layout.members_by_org_list, null);
viewHolder = new MembersByOrgAdapter.ViewHolder(finalView); viewHolder = new MembersByOrgAdapter.ViewHolder(finalView);
finalView.setTag(viewHolder); finalView.setTag(viewHolder);
} }
@ -83,7 +83,7 @@ public class MembersByOrgAdapter extends BaseAdapter implements Filterable {
private void initData(MembersByOrgAdapter.ViewHolder viewHolder, int position) { private void initData(MembersByOrgAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = membersList.get(position); UserInfo currentItem = membersList.get(position);
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(viewHolder.memberAvatar); Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(viewHolder.memberAvatar);
if(!currentItem.getFullname().equals("")) { if(!currentItem.getFullname().equals("")) {
viewHolder.memberName.setText(currentItem.getFullname()); viewHolder.memberName.setText(currentItem.getFullname());

View File

@ -2,36 +2,38 @@ 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;
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.Filter;
import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import com.amulyakhare.textdrawable.TextDrawable;
import androidx.recyclerview.widget.RecyclerView;
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;
import org.mian.gitnex.actions.MilestoneActions;
import org.mian.gitnex.helpers.ClickListener; import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TimeHelper; import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.Milestones; import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.util.TinyDB;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; 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;
@ -40,6 +42,7 @@ 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;
@ -52,348 +55,279 @@ import io.noties.markwon.linkify.LinkifyPlugin;
* Author M M Arif * Author M M Arif
*/ */
public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class MilestonesAdapter extends RecyclerView.Adapter<MilestonesAdapter.MilestonesViewHolder> implements Filterable {
private Context context; private List<Milestones> milestonesList;
private final int TYPE_LOAD = 0; private Context mCtx;
private List<Milestones> dataList; private List<Milestones> milestonesListFull;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false; static class MilestonesViewHolder extends RecyclerView.ViewHolder {
private boolean isMoreDataAvailable = true;
private String TAG = StaticGlobalVariables.tagMilestonesAdapter; private TextView msTitle;
private TextView msDescription;
public MilestonesAdapter(Context context, List<Milestones> dataListMain) { private TextView msOpenIssues;
private TextView msClosedIssues;
this.context = context; private TextView msDueDate;
this.dataList = dataListMain; private ImageView msStatus;
private ProgressBar msProgress;
}
private MilestonesViewHolder(View itemView) {
@NonNull super(itemView);
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { msTitle = itemView.findViewById(R.id.milestoneTitle);
msStatus = itemView.findViewById(R.id.milestoneState);
LayoutInflater inflater = LayoutInflater.from(context); msDescription = itemView.findViewById(R.id.milestoneDescription);
msOpenIssues = itemView.findViewById(R.id.milestoneIssuesOpen);
if(viewType == TYPE_LOAD) { msClosedIssues = itemView.findViewById(R.id.milestoneIssuesClosed);
return new MilestonesAdapter.DataHolder(inflater.inflate(R.layout.list_milestones, parent, false)); msDueDate = itemView.findViewById(R.id.milestoneDueDate);
} msProgress = itemView.findViewById(R.id.milestoneProgress);
else {
return new MilestonesAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false)); /*msTitle.setOnClickListener(new View.OnClickListener() {
} @Override
public void onClick(View v) {
}
Context context = v.getContext();
@Override Log.i("issueNumber", issueNumber.getText().toString());
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Intent intent = new Intent(context, IssueDetailActivity.class);
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) { intent.putExtra("issueNumber", issueNumber.getText());
isLoading = true; TinyDB tinyDb = new TinyDB(context);
loadMoreListener.onLoadMore(); tinyDb.putString("issueNumber", issueNumber.getText().toString());
context.startActivity(intent);
}
}
if(getItemViewType(position) == TYPE_LOAD) { });*/
}
((MilestonesAdapter.DataHolder) holder).bindData(dataList.get(position)); }
} public MilestonesAdapter(Context mCtx, List<Milestones> milestonesMain) {
this.mCtx = mCtx;
} this.milestonesList = milestonesMain;
milestonesListFull = new ArrayList<>(milestonesList);
class DataHolder extends RecyclerView.ViewHolder { }
private TextView milestoneId; @NonNull
private TextView msTitle; @Override
private TextView msDescription; public MilestonesAdapter.MilestonesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
private TextView msOpenIssues; View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.milestones_list, parent, false);
private TextView msClosedIssues; return new MilestonesAdapter.MilestonesViewHolder(v);
private TextView msDueDate; }
private ProgressBar msProgress;
private TextView milestoneStatus; @Override
public void onBindViewHolder(@NonNull MilestonesAdapter.MilestonesViewHolder holder, int position) {
DataHolder(View itemView) {
final TinyDB tinyDb = new TinyDB(mCtx);
super(itemView); final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
milestoneId = itemView.findViewById(R.id.milestoneId);
msTitle = itemView.findViewById(R.id.milestoneTitle); Milestones currentItem = milestonesList.get(position);
msDescription = itemView.findViewById(R.id.milestoneDescription);
msOpenIssues = itemView.findViewById(R.id.milestoneIssuesOpen); final Markwon markwon = Markwon.builder(Objects.requireNonNull(mCtx))
msClosedIssues = itemView.findViewById(R.id.milestoneIssuesClosed); .usePlugin(CorePlugin.create())
msDueDate = itemView.findViewById(R.id.milestoneDueDate); .usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
msProgress = itemView.findViewById(R.id.milestoneProgress); @Override
ImageView milestonesMenu = itemView.findViewById(R.id.milestonesMenu); public void configureImages(@NonNull ImagesPlugin plugin) {
milestoneStatus = itemView.findViewById(R.id.milestoneStatus); plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
milestonesMenu.setOnClickListener(v -> { @Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
Context ctx = v.getContext();
int milestoneId_ = Integer.parseInt(milestoneId.getText().toString()); final int resourceId = mCtx.getResources().getIdentifier(
raw.substring("drawable://".length()),
@SuppressLint("InflateParams") View view = LayoutInflater.from(ctx).inflate(R.layout.bottom_sheet_milestones_in_list, null); "drawable",
mCtx.getPackageName());
TextView closeMilestone = view.findViewById(R.id.closeMilestone);
TextView openMilestone = view.findViewById(R.id.openMilestone); final Drawable drawable = mCtx.getDrawable(resourceId);
BottomSheetDialog dialog = new BottomSheetDialog(ctx); assert drawable != null;
dialog.setContentView(view); return ImageItem.withResult(drawable);
dialog.show(); }
if(milestoneStatus.getText().toString().equals("open")) { @NonNull
@Override
closeMilestone.setVisibility(View.VISIBLE); public Collection<String> supportedSchemes() {
openMilestone.setVisibility(View.GONE); return Collections.singleton("drawable");
}
} });
else { plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
@Nullable
closeMilestone.setVisibility(View.GONE); @Override
openMilestone.setVisibility(View.VISIBLE); public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
return null;
} }
});
closeMilestone.setOnClickListener(v12 -> { plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources()));
MilestoneActions.closeMilestone(ctx, milestoneId_); plugin.addMediaDecoder(SvgMediaDecoder.create());
dialog.dismiss(); plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources()));
updateAdapter(getAdapterPosition()); plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}
}); }))
.usePlugin(new AbstractMarkwonPlugin() {
openMilestone.setOnClickListener(v12 -> { @Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
MilestoneActions.openMilestone(ctx, milestoneId_); builder
dialog.dismiss(); .codeTextColor(tinyDb.getInt("codeBlockColor"))
updateAdapter(getAdapterPosition()); .codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(mCtx.getResources().getColor(R.color.lightBlue));
}); }
})
}); .usePlugin(TablePlugin.create(mCtx))
.usePlugin(TaskListPlugin.create(mCtx))
} .usePlugin(HtmlPlugin.create())
.usePlugin(StrikethroughPlugin.create())
@SuppressLint("SetTextI18n") .usePlugin(LinkifyPlugin.create())
void bindData(Milestones dataModel) { .build();
final TinyDB tinyDb = new TinyDB(context); Spanned msTitle = markwon.toMarkdown(currentItem.getTitle());
final String locale = tinyDb.getString("locale"); markwon.setParsedMarkdown(holder.msTitle, msTitle);
final String timeFormat = tinyDb.getString("dateFormat"); //holder.msStatus.setText(currentItem.getState());
milestoneId.setText(String.valueOf(dataModel.getId())); if(currentItem.getState().equals("open")) {
milestoneStatus.setText(dataModel.getState());
@SuppressLint("ResourceType") int color = Color.parseColor(mCtx.getResources().getString(R.color.releaseStable));
Markwon markwon = Markwon.builder(Objects.requireNonNull(context)).usePlugin(CorePlugin.create()).usePlugin(ImagesPlugin.create(plugin -> { TextDrawable drawable = TextDrawable.builder()
plugin.addSchemeHandler(new SchemeHandler() { .beginConfig()
//.useFont(Typeface.DEFAULT)
@NonNull .textColor(mCtx.getResources().getColor(R.color.white))
@Override .fontSize(30)
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) { .toUpperCase()
.width(120)
final int resourceId = context.getResources().getIdentifier( .height(60)
raw.substring("drawable://".length()), .endConfig()
"drawable", .buildRoundRect("open", color, 8);
context.getPackageName());
holder.msStatus.setImageDrawable(drawable);
final Drawable drawable = context.getDrawable(resourceId);
}
assert drawable != null; else if(currentItem.getState().equals("closed")) {
return ImageItem.withResult(drawable);
} @SuppressLint("ResourceType") int color = Color.parseColor(mCtx.getResources().getString(R.color.colorRed));
TextDrawable drawable = TextDrawable.builder()
@NonNull .beginConfig()
@Override //.useFont(Typeface.DEFAULT)
public Collection<String> supportedSchemes() { .textColor(mCtx.getResources().getColor(R.color.white))
return Collections.singleton("drawable"); .fontSize(30)
} .toUpperCase()
}); .width(140)
.height(60)
plugin.placeholderProvider(drawable -> null); .endConfig()
plugin.addMediaDecoder(GifMediaDecoder.create(false)); .buildRoundRect("closed", color, 8);
plugin.addMediaDecoder(SvgMediaDecoder.create(context.getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create()); holder.msStatus.setImageDrawable(drawable);
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(context.getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create()); }
})) if (!currentItem.getDescription().equals("")) {
final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(currentItem.getDescription()));
.usePlugin(new AbstractMarkwonPlugin() { holder.msDescription.setText(bodyWithMD);
@Override }
public void configureTheme(@NonNull MarkwonTheme.Builder builder) { else {
builder holder.msDescription.setVisibility(View.GONE);
.codeTextColor(tinyDb.getInt("codeBlockColor")) }
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(context.getResources().getColor(R.color.lightBlue)); holder.msOpenIssues.setText(String.valueOf(currentItem.getOpen_issues()));
} holder.msOpenIssues.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.milestoneOpenIssues, currentItem.getOpen_issues()), mCtx));
})
.usePlugin(TablePlugin.create(context)) holder.msClosedIssues.setText(String.valueOf(currentItem.getClosed_issues()));
.usePlugin(TaskListPlugin.create(context)) holder.msClosedIssues.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.milestoneClosedIssues, currentItem.getClosed_issues()), mCtx));
.usePlugin(HtmlPlugin.create())
.usePlugin(StrikethroughPlugin.create()) if ((currentItem.getOpen_issues() + currentItem.getClosed_issues()) > 0) {
.usePlugin(LinkifyPlugin.create())
.build(); if (currentItem.getOpen_issues() == 0) {
holder.msProgress.setProgress(100);
Spanned msTitle_ = markwon.toMarkdown(dataModel.getTitle()); holder.msProgress.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.milestoneCompletion, 100), mCtx));
markwon.setParsedMarkdown(msTitle, msTitle_); }
else {
if(!dataModel.getDescription().equals("")) { int msCompletion = 100 * currentItem.getClosed_issues() / (currentItem.getOpen_issues() + currentItem.getClosed_issues());
holder.msProgress.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.milestoneCompletion, msCompletion), mCtx));
CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(dataModel.getDescription())); holder.msProgress.setProgress(msCompletion);
msDescription.setText(bodyWithMD); }
} }
else { else {
holder.msProgress.setProgress(0);
msDescription.setText(context.getString(R.string.milestoneNoDescription)); holder.msProgress.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.milestoneCompletion, 0), mCtx));
} }
msOpenIssues.setText(context.getString(R.string.milestoneIssueStatusOpen, dataModel.getOpen_issues())); if(currentItem.getDue_on() != null) {
msClosedIssues.setText(context.getString(R.string.milestoneIssueStatusClosed, dataModel.getClosed_issues()));
if (timeFormat.equals("normal") || timeFormat.equals("pretty")) {
if((dataModel.getOpen_issues() + dataModel.getClosed_issues()) > 0) { DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", new Locale(locale));
Date date = null;
if(dataModel.getOpen_issues() == 0) { try {
date = formatter.parse(currentItem.getDue_on());
msProgress.setProgress(100); } catch (ParseException e) {
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 100), context)); e.printStackTrace();
}
} String dueDate = formatter.format(date);
else { assert date != null;
if(date.before(new Date())) {
int msCompletion = 100 * dataModel.getClosed_issues() / (dataModel.getOpen_issues() + dataModel.getClosed_issues()); holder.msDueDate.setTextColor(mCtx.getResources().getColor(R.color.darkRed));
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, msCompletion), context)); }
msProgress.setProgress(msCompletion);
holder.msDueDate.setText(dueDate);
} holder.msDueDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToast(currentItem.getDue_on()), mCtx));
} } else if (timeFormat.equals("normal1")) {
else { SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", new Locale(locale));
Date date1 = null;
msProgress.setProgress(0); try {
msProgress.setOnClickListener(new ClickListener(context.getResources().getString(R.string.milestoneCompletion, 0), context)); date1 = formatter.parse(currentItem.getDue_on());
} catch (ParseException e) {
} e.printStackTrace();
}
if(dataModel.getDue_on() != null) { String dueDate = formatter.format(date1);
holder.msDueDate.setText(dueDate);
if(timeFormat.equals("normal") || timeFormat.equals("pretty")) { }
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", new Locale(locale)); }
Date date = null; else {
holder.msDueDate.setVisibility(View.GONE);
try { }
date = formatter.parse(dataModel.getDue_on());
} }
catch(ParseException e) {
Log.e(TAG, e.toString()); @Override
} public int getItemCount() {
return milestonesList.size();
assert date != null; }
String dueDate = formatter.format(date);
@Override
if(date.before(new Date())) { public Filter getFilter() {
msDueDate.setTextColor(context.getResources().getColor(R.color.darkRed)); return milestoneFilter;
} }
msDueDate.setText(dueDate); private Filter milestoneFilter = new Filter() {
msDueDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToast(dataModel.getDue_on()), context)); @Override
protected FilterResults performFiltering(CharSequence constraint) {
} List<Milestones> filteredList = new ArrayList<>();
else if(timeFormat.equals("normal1")) {
if (constraint == null || constraint.length() == 0) {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", new Locale(locale)); filteredList.addAll(milestonesListFull);
} else {
Date date1 = null; String filterPattern = constraint.toString().toLowerCase().trim();
try { for (Milestones item : milestonesListFull) {
date1 = formatter.parse(dataModel.getDue_on()); if (item.getTitle().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
} filteredList.add(item);
catch(ParseException e) { }
Log.e(TAG, e.toString()); }
} }
assert date1 != null; FilterResults results = new FilterResults();
String dueDate = formatter.format(date1); results.values = filteredList;
msDueDate.setText(dueDate);
return results;
} }
} @Override
else { protected void publishResults(CharSequence constraint, FilterResults results) {
milestonesList.clear();
msDueDate.setText(context.getString(R.string.milestoneNoDueDate)); milestonesList.addAll((List) results.values);
} notifyDataSetChanged();
}
} };
}
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,14 +11,14 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.models.MultiSelectModel;
import java.util.ArrayList;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatCheckBox; import androidx.appcompat.widget.AppCompatCheckBox;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.models.MultiSelectModel;
import java.util.List;
/** /**
* Author com.github.abumoallim, modified by M M Arif * Author com.github.abumoallim, modified by M M Arif
@ -26,11 +26,11 @@ import java.util.List;
public class MutliSelectAdapter extends RecyclerView.Adapter<MutliSelectAdapter.MultiSelectDialogViewHolder> { public class MutliSelectAdapter extends RecyclerView.Adapter<MutliSelectAdapter.MultiSelectDialogViewHolder> {
private List<MultiSelectModel> mDataSet; private ArrayList<MultiSelectModel> mDataSet;
private String mSearchQuery = ""; private String mSearchQuery = "";
private Context mContext; private Context mContext;
public MutliSelectAdapter(List<MultiSelectModel> dataSet, Context context) { public MutliSelectAdapter(ArrayList<MultiSelectModel> dataSet, Context context) {
this.mDataSet = dataSet; this.mDataSet = dataSet;
this.mContext = context; this.mContext = context;
} }
@ -163,7 +163,7 @@ public class MutliSelectAdapter extends RecyclerView.Adapter<MutliSelectAdapter.
return mDataSet.size(); return mDataSet.size();
} }
public void setData(List<MultiSelectModel> data, String query, MutliSelectAdapter mutliSelectAdapter) { public void setData(ArrayList<MultiSelectModel> data, String query, MutliSelectAdapter mutliSelectAdapter) {
this.mDataSet = data; this.mDataSet = data;
this.mSearchQuery = query; this.mSearchQuery = query;
@ -187,4 +187,4 @@ public class MutliSelectAdapter extends RecyclerView.Adapter<MutliSelectAdapter.
} }
} }
} }

View File

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

View File

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

View File

@ -1,6 +1,7 @@
package org.mian.gitnex.adapters; package org.mian.gitnex.adapters;
import android.annotation.SuppressLint; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -10,14 +11,12 @@ import android.widget.Filter;
import android.widget.Filterable; import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import com.squareup.picasso.Picasso;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.OrganizationDetailActivity; import org.mian.gitnex.activities.OrgDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserOrganizations; import org.mian.gitnex.models.UserOrganizations;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -36,27 +35,23 @@ public class OrganizationsListAdapter extends RecyclerView.Adapter<Organizations
private ImageView image; private ImageView image;
private TextView mTextView1; private TextView mTextView1;
private TextView mTextView2; private TextView mTextView2;
private TextView organizationId;
private OrganizationsViewHolder(View itemView) { private OrganizationsViewHolder(View itemView) {
super(itemView); super(itemView);
mTextView1 = itemView.findViewById(R.id.orgUsername); mTextView1 = itemView.findViewById(R.id.orgUsername);
mTextView2 = itemView.findViewById(R.id.orgDescription); mTextView2 = itemView.findViewById(R.id.orgDescription);
image = itemView.findViewById(R.id.imageAvatar); image = itemView.findViewById(R.id.imageAvatar);
organizationId = itemView.findViewById(R.id.organizationId);
itemView.setOnClickListener(new View.OnClickListener() { itemView.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
Context context = v.getContext(); Context context = v.getContext();
Intent intent = new Intent(context, OrganizationDetailActivity.class); Intent intent = new Intent(context, OrgDetailActivity.class);
intent.putExtra("orgName", mTextView1.getText().toString()); intent.putExtra("orgName", mTextView1.getText().toString());
TinyDB tinyDb = new TinyDB(context); TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("orgName", mTextView1.getText().toString()); tinyDb.putString("orgName", mTextView1.getText().toString());
tinyDb.putString("organizationId", organizationId.getText().toString());
tinyDb.putBoolean("organizationAction", true);
context.startActivity(intent); context.startActivity(intent);
} }
@ -74,19 +69,17 @@ public class OrganizationsListAdapter extends RecyclerView.Adapter<Organizations
@NonNull @NonNull
@Override @Override
public OrganizationsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public OrganizationsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_organizations, parent, false); View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.organizations_list, parent, false);
return new OrganizationsViewHolder(v); return new OrganizationsViewHolder(v);
} }
@SuppressLint("SetTextI18n")
@Override @Override
public void onBindViewHolder(@NonNull OrganizationsViewHolder holder, int position) { public void onBindViewHolder(@NonNull OrganizationsViewHolder holder, int position) {
UserOrganizations currentItem = orgList.get(position); UserOrganizations currentItem = orgList.get(position);
holder.mTextView2.setVisibility(View.GONE); holder.mTextView2.setVisibility(View.GONE);
holder.organizationId.setText(Integer.toString(currentItem.getId()));
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image); Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
holder.mTextView1.setText(currentItem.getUsername()); holder.mTextView1.setText(currentItem.getUsername());
if (!currentItem.getDescription().equals("")) { if (!currentItem.getDescription().equals("")) {
holder.mTextView2.setVisibility(View.VISIBLE); holder.mTextView2.setVisibility(View.VISIBLE);

View File

@ -44,7 +44,7 @@ public class ProfileEmailsAdapter extends RecyclerView.Adapter<ProfileEmailsAdap
@NonNull @NonNull
@Override @Override
public ProfileEmailsAdapter.EmailsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ProfileEmailsAdapter.EmailsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_profile_emails, parent, false); View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.profile_emails_list, parent, false);
return new ProfileEmailsAdapter.EmailsViewHolder(v); return new ProfileEmailsAdapter.EmailsViewHolder(v);
} }
@ -58,7 +58,7 @@ public class ProfileEmailsAdapter extends RecyclerView.Adapter<ProfileEmailsAdap
if(currentItem.getPrimary()) { if(currentItem.getPrimary()) {
TextDrawable drawable = TextDrawable.builder() TextDrawable drawable = TextDrawable.builder()
.beginConfig() .beginConfig()
.textColor(mCtx.getResources().getColor(R.color.colorWhite)) .textColor(mCtx.getResources().getColor(R.color.white))
.fontSize(36) .fontSize(36)
.width(220) .width(220)
.height(60) .height(60)

View File

@ -6,8 +6,8 @@ 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.squareup.picasso.Picasso;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo; import org.mian.gitnex.models.UserInfo;
import java.util.List; import java.util.List;
@ -47,7 +47,7 @@ public class ProfileFollowersAdapter extends RecyclerView.Adapter<ProfileFollowe
@NonNull @NonNull
@Override @Override
public ProfileFollowersAdapter.FollowersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ProfileFollowersAdapter.FollowersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_profile_followers, parent, false); View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.profile_followers_list, parent, false);
return new ProfileFollowersAdapter.FollowersViewHolder(v); return new ProfileFollowersAdapter.FollowersViewHolder(v);
} }
@ -65,7 +65,7 @@ public class ProfileFollowersAdapter extends RecyclerView.Adapter<ProfileFollowe
holder.userName.setVisibility(View.GONE); holder.userName.setVisibility(View.GONE);
} }
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar); Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
} }
@Override @Override

View File

@ -6,8 +6,8 @@ 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.squareup.picasso.Picasso;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.UserInfo; import org.mian.gitnex.models.UserInfo;
import java.util.List; import java.util.List;
@ -47,7 +47,7 @@ public class ProfileFollowingAdapter extends RecyclerView.Adapter<ProfileFollowi
@NonNull @NonNull
@Override @Override
public ProfileFollowingAdapter.FollowingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ProfileFollowingAdapter.FollowingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_profile_following, parent, false); View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.profile_following_list, parent, false);
return new ProfileFollowingAdapter.FollowingViewHolder(v); return new ProfileFollowingAdapter.FollowingViewHolder(v);
} }
@ -65,7 +65,7 @@ public class ProfileFollowingAdapter extends RecyclerView.Adapter<ProfileFollowi
holder.userName.setVisibility(View.GONE); holder.userName.setVisibility(View.GONE);
} }
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar); Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar);
} }
@Override @Override

View File

@ -7,19 +7,25 @@ import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.activities.IssueDetailActivity; import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.ClickListener; import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper; import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.PullRequests; import org.mian.gitnex.models.PullRequests;
import org.mian.gitnex.util.TinyDB;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -27,229 +33,247 @@ import java.util.Locale;
* Author M M Arif * Author M M Arif
*/ */
public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {
private Context context; private Context context;
private final int TYPE_LOAD = 0; private final int TYPE_LOAD = 0;
private List<PullRequests> prList; private List<PullRequests> prList;
private PullRequestsAdapter.OnLoadMoreListener loadMoreListener; private List<PullRequests> prListFull;
private boolean isLoading = false, isMoreDataAvailable = true; private PullRequestsAdapter.OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
public PullRequestsAdapter(Context context, List<PullRequests> prListMain) { public PullRequestsAdapter(Context context, List<PullRequests> prListMain) {
this.context = context; this.context = context;
this.prList = prListMain; this.prList = prListMain;
prListFull = new ArrayList<>(prList);
} }
@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 PullRequestsAdapter.PullRequestsHolder(inflater.inflate(R.layout.list_pr, parent, false)); return new PullRequestsAdapter.PullRequestsHolder(inflater.inflate(R.layout.repo_pr_list, parent,false));
} }
else { else {
return new PullRequestsAdapter.LoadHolder(inflater.inflate(R.layout.row_load, parent, false)); return new PullRequestsAdapter.LoadHolder(inflater.inflate(R.layout.row_load,parent,false));
} }
} }
@Override @Override
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) {
((PullRequestsAdapter.PullRequestsHolder) holder).bindData(prList.get(position)); ((PullRequestsAdapter.PullRequestsHolder)holder).bindData(prList.get(position));
} }
} }
@Override @Override
public int getItemViewType(int position) { public int getItemViewType(int position) {
if(prList.get(position).getTitle() != null) { if(prList.get(position).getTitle() != null) {
return TYPE_LOAD; return TYPE_LOAD;
} }
else { else {
return 1; return 1;
} }
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return prList.size(); return prList.size();
} }
class PullRequestsHolder extends RecyclerView.ViewHolder { class PullRequestsHolder extends RecyclerView.ViewHolder {
private TextView prNumber; private TextView prNumber;
private TextView prMergeable; private ImageView assigneeAvatar;
private TextView prHeadBranch; private TextView prTitle;
private TextView prIsFork; private TextView prCreatedTime;
private TextView prForkFullName; private TextView prCommentsCount;
private ImageView assigneeAvatar;
private TextView prTitle;
private TextView prCreatedTime;
private TextView prCommentsCount;
PullRequestsHolder(View itemView) { PullRequestsHolder(View itemView) {
super(itemView); super(itemView);
prNumber = itemView.findViewById(R.id.prNumber); prNumber = itemView.findViewById(R.id.prNumber);
prMergeable = itemView.findViewById(R.id.prMergeable); assigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
prHeadBranch = itemView.findViewById(R.id.prHeadBranch); prTitle = itemView.findViewById(R.id.prTitle);
prIsFork = itemView.findViewById(R.id.prIsFork); prCommentsCount = itemView.findViewById(R.id.prCommentsCount);
prForkFullName = itemView.findViewById(R.id.prForkFullName); LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount);
assigneeAvatar = itemView.findViewById(R.id.assigneeAvatar); prCreatedTime = itemView.findViewById(R.id.prCreatedTime);
prTitle = itemView.findViewById(R.id.prTitle);
prCommentsCount = itemView.findViewById(R.id.prCommentsCount);
LinearLayout frameCommentsCount = itemView.findViewById(R.id.frameCommentsCount);
prCreatedTime = itemView.findViewById(R.id.prCreatedTime);
prTitle.setOnClickListener(v -> { prTitle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext(); Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class); Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", prNumber.getText()); intent.putExtra("issueNumber", prNumber.getText());
intent.putExtra("prMergeable", prMergeable.getText());
intent.putExtra("prHeadBranch", prHeadBranch.getText());
TinyDB tinyDb = new TinyDB(context); TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", prNumber.getText().toString()); tinyDb.putString("issueNumber", prNumber.getText().toString());
tinyDb.putString("prMergeable", prMergeable.getText().toString()); tinyDb.putString("issueType", "pr");
tinyDb.putString("prHeadBranch", prHeadBranch.getText().toString()); context.startActivity(intent);
tinyDb.putString("prIsFork", prIsFork.getText().toString());
tinyDb.putString("prForkFullName", prForkFullName.getText().toString());
tinyDb.putString("issueType", "Pull");
context.startActivity(intent);
}); }
frameCommentsCount.setOnClickListener(v -> { });
frameCommentsCount.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext(); Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class); Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", prNumber.getText()); intent.putExtra("issueNumber", prNumber.getText());
intent.putExtra("prMergeable", prMergeable.getText());
intent.putExtra("prHeadBranch", prHeadBranch.getText());
TinyDB tinyDb = new TinyDB(context); TinyDB tinyDb = new TinyDB(context);
tinyDb.putString("issueNumber", prNumber.getText().toString()); tinyDb.putString("issueNumber", prNumber.getText().toString());
tinyDb.putString("prMergeable", prMergeable.getText().toString()); tinyDb.putString("issueType", "pr");
tinyDb.putString("prHeadBranch", prHeadBranch.getText().toString()); context.startActivity(intent);
tinyDb.putString("prIsFork", prIsFork.getText().toString());
tinyDb.putString("prForkFullName", prForkFullName.getText().toString());
tinyDb.putString("issueType", "Pull");
context.startActivity(intent);
}); }
});
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
void bindData(PullRequests prModel) { void bindData(PullRequests prModel){
final TinyDB tinyDb = new TinyDB(context); final TinyDB tinyDb = new TinyDB(context);
final String locale = tinyDb.getString("locale"); final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat"); final String timeFormat = tinyDb.getString("dateFormat");
if(!prModel.getUser().getFull_name().equals("")) { if (!prModel.getUser().getFull_name().equals("")) {
assigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.prCreator) + prModel.getUser().getFull_name(), context)); assigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.prCreator) + prModel.getUser().getFull_name(), context));
} } else {
else { assigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.prCreator) + prModel.getUser().getLogin(), context));
assigneeAvatar.setOnClickListener(new ClickListener(context.getResources().getString(R.string.prCreator) + prModel.getUser().getLogin(), context)); }
}
if(prModel.getUser().getAvatar_url() != null) { if (prModel.getUser().getAvatar_url() != null) {
PicassoService.getInstance(context).get().load(prModel.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar); Picasso.get().load(prModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar);
} } else {
else { Picasso.get().load(prModel.getUser().getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar);
PicassoService.getInstance(context).get().load(prModel.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar); }
}
String prNumber_ = "<font color='" + context.getResources().getColor(R.color.lightGray) + "'>" + context.getResources().getString(R.string.hash) + prModel.getNumber() + "</font>"; String prNumber_ = "<font color='" + context.getResources().getColor(R.color.lightGray) + "'>" + context.getResources().getString(R.string.hash) + prModel.getNumber() + "</font>";
prTitle.setText(Html.fromHtml(prNumber_ + " " + prModel.getTitle())); prTitle.setText(Html.fromHtml(prNumber_ + " " + prModel.getTitle()));
prNumber.setText(String.valueOf(prModel.getNumber())); prNumber.setText(String.valueOf(prModel.getNumber()));
prMergeable.setText(String.valueOf(prModel.isMergeable())); prCommentsCount.setText(String.valueOf(prModel.getComments()));
if(prModel.getHead() != null) {
prHeadBranch.setText(prModel.getHead().getRef());
if(prModel.getHead().getRepo() != null) {
prIsFork.setText(String.valueOf(prModel.getHead().getRepo().isFork()));
prForkFullName.setText(prModel.getHead().getRepo().getFull_name());
}
else {
// pull was done from a deleted fork
prIsFork.setText("true");
prForkFullName.setText(context.getString(R.string.prDeletedFrok));
}
}
prCommentsCount.setText(String.valueOf(prModel.getComments()));
prCreatedTime.setText(TimeHelper.formatTime(prModel.getCreated_at(), new Locale(locale), timeFormat, context)); switch (timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(prModel.getCreated_at());
prCreatedTime.setText(createdTime);
prCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(prModel.getCreated_at()), context));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(prModel.getCreated_at());
prCreatedTime.setText(createdTime);
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(prModel.getCreated_at());
prCreatedTime.setText(createdTime);
break;
}
}
if(timeFormat.equals("pretty")) { }
prCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(prModel.getCreated_at()), context));
}
} }
} static class LoadHolder extends RecyclerView.ViewHolder {
static class LoadHolder extends RecyclerView.ViewHolder { LoadHolder(View itemView) {
super(itemView);
}
LoadHolder(View itemView) { }
super(itemView); public void setMoreDataAvailable(boolean moreDataAvailable) {
}
} isMoreDataAvailable = moreDataAvailable;
public void setMoreDataAvailable(boolean moreDataAvailable) { }
isMoreDataAvailable = moreDataAvailable; public void notifyDataChanged() {
} notifyDataSetChanged();
isLoading = false;
public void notifyDataChanged() { }
notifyDataSetChanged(); public interface OnLoadMoreListener {
isLoading = false;
} void onLoadMore();
public interface OnLoadMoreListener { }
void onLoadMore(); public void setLoadMoreListener(PullRequestsAdapter.OnLoadMoreListener loadMoreListener) {
} this.loadMoreListener = loadMoreListener;
public void setLoadMoreListener(PullRequestsAdapter.OnLoadMoreListener loadMoreListener) { }
this.loadMoreListener = loadMoreListener; @Override
public Filter getFilter() {
return prFilter;
}
} private Filter prFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<PullRequests> filteredList = new ArrayList<>();
public void updateList(List<PullRequests> list) { if (constraint == null || constraint.length() == 0) {
filteredList.addAll(prList);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
prList = list; for (PullRequests item : prList) {
notifyDataSetChanged(); if (item.getTitle().toLowerCase().contains(filterPattern) || item.getBody().toLowerCase().contains(filterPattern)) {
} filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
prList.clear();
prList.addAll((List) results.values);
notifyDataSetChanged();
}
};
} }

View File

@ -10,25 +10,19 @@ 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 androidx.annotation.NonNull; import com.amulyakhare.textdrawable.TextDrawable;
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.helpers.TinyDB;
import org.mian.gitnex.models.Releases; import org.mian.gitnex.models.Releases;
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;
@ -37,6 +31,7 @@ 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;
@ -54,44 +49,25 @@ 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 TextView releaseType; private ImageView releaseType;
private TextView releaseName; private TextView releaseTitle;
private ImageView authorAvatar; private TextView releaseDescription;
private TextView authorName; private TextView releaseDownload;
private TextView releaseTag;
private TextView releaseCommitSha;
private TextView releaseDate;
private TextView releaseBodyContent;
private LinearLayout downloadFrame;
private RelativeLayout downloads;
private TextView releaseZipDownload; private TextView releaseZipDownload;
private TextView releaseTarDownload; private TextView releaseTarDownload;
private ImageView downloadDropdownIcon; private TextView releaseTag;
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);
releaseName = itemView.findViewById(R.id.releaseName); releaseTitle = itemView.findViewById(R.id.releaseTitle);
authorAvatar = itemView.findViewById(R.id.authorAvatar); releaseDescription = itemView.findViewById(R.id.releaseDescription);
authorName = itemView.findViewById(R.id.authorName); releaseZipDownload = itemView.findViewById(R.id.releaseZipDownload);
releaseTag = itemView.findViewById(R.id.releaseTag); releaseTarDownload = itemView.findViewById(R.id.releaseTarDownload);
releaseCommitSha = itemView.findViewById(R.id.releaseCommitSha); releaseTag = itemView.findViewById(R.id.releaseTag);
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()));
} }
} }
@ -104,7 +80,7 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
@NonNull @NonNull
@Override @Override
public ReleasesAdapter.ReleasesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ReleasesAdapter.ReleasesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_releases, parent, false); View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.releases_list, parent, false);
return new ReleasesAdapter.ReleasesViewHolder(v); return new ReleasesAdapter.ReleasesViewHolder(v);
} }
@ -112,74 +88,83 @@ 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.releaseName.setText(currentItem.getName()); holder.releaseTitle.setText(currentItem.getName());
if(currentItem.isPrerelease()) { if(!currentItem.getTag_name().equals("")) {
holder.releaseType.setBackgroundResource(R.drawable.shape_pre_release); holder.releaseTag.setText(mCtx.getResources().getString(R.string.releaseTag, currentItem.getTag_name()));
holder.releaseType.setText(R.string.releaseTypePre); }
} else {
else if(currentItem.isDraft()) { holder.releaseTag.setVisibility(View.GONE);
holder.releaseType.setVisibility(View.GONE); }
}
else {
holder.releaseType.setBackgroundResource(R.drawable.shape_stable_release);
holder.releaseType.setText(R.string.releaseTypeStable);
}
if(currentItem.getAuthor().getAvatar_url() != null) { if(currentItem.isPrerelease()) {
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); TextDrawable drawable = TextDrawable.builder()
} .beginConfig()
//.useFont(Typeface.DEFAULT)
holder.authorName.setText(mCtx.getResources().getString(R.string.releasePublishedBy, currentItem.getAuthor().getUsername())); .textColor(mCtx.getResources().getColor(R.color.white))
.fontSize(34)
if(currentItem.getTag_name() != null) { .width(260)
holder.releaseTag.setText(currentItem.getTag_name()); .height(60)
} .endConfig()
.buildRoundRect(mCtx.getResources().getString(R.string.releaseTypePre), mCtx.getResources().getColor(R.color.releasePre), 8);
if(currentItem.getPublished_at() != null) { holder.releaseType.setImageDrawable(drawable);
holder.releaseDate.setText(TimeHelper.formatTime(currentItem.getPublished_at(), new Locale(locale), timeFormat, mCtx)); }
} else {
TextDrawable drawable = TextDrawable.builder()
if(timeFormat.equals("pretty")) { .beginConfig()
holder.releaseDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getPublished_at()), mCtx)); //.useFont(Typeface.DEFAULT)
} .textColor(mCtx.getResources().getColor(R.color.white))
.fontSize(34)
.width(260)
.height(60)
.endConfig()
.buildRoundRect(mCtx.getResources().getString(R.string.releaseTypeStable), mCtx.getResources().getColor(R.color.releaseStable), 8);
holder.releaseType.setImageDrawable(drawable);
}
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(plugin -> { .usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
plugin.addSchemeHandler(new SchemeHandler() { @Override
@NonNull public void configureImages(@NonNull ImagesPlugin plugin) {
@Override plugin.addSchemeHandler(new SchemeHandler() {
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) { @NonNull
@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(drawable -> null); plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
plugin.addMediaDecoder(GifMediaDecoder.create(false)); @Nullable
plugin.addMediaDecoder(SvgMediaDecoder.create(mCtx.getResources())); @Override
plugin.addMediaDecoder(SvgMediaDecoder.create()); public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(mCtx.getResources())); return null;
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
@ -200,29 +185,12 @@ 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.releaseBodyContent, bodyWithMD); markwon.setParsedMarkdown(holder.releaseDescription, bodyWithMD);
} }
else { else {
holder.releaseBodyContent.setText(R.string.noReleaseBodyContent); holder.releaseDescription.setVisibility(View.GONE);
} }
holder.downloadFrame.setOnClickListener(v -> {
if(holder.downloads.getVisibility() == View.GONE) {
holder.downloadDropdownIcon.setImageResource(R.drawable.ic_chevron_down);
holder.downloads.setVisibility(View.VISIBLE);
}
else {
holder.downloadDropdownIcon.setImageResource(R.drawable.ic_chevron_right);
holder.downloads.setVisibility(View.GONE);
}
});
holder.releaseZipDownload.setText( 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());
@ -231,9 +199,6 @@ 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

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

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

View File

@ -2,17 +2,15 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
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.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.RoundedTransformation; import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserInfo; import org.mian.gitnex.models.UserInfo;
import java.util.List; import java.util.List;
@ -25,7 +23,7 @@ public class RepoStargazersAdapter extends BaseAdapter {
private List<UserInfo> stargazersList; private List<UserInfo> stargazersList;
private Context mCtx; private Context mCtx;
private static class ViewHolder { private class ViewHolder {
private ImageView memberAvatar; private ImageView memberAvatar;
private TextView memberName; private TextView memberName;
@ -63,8 +61,8 @@ public class RepoStargazersAdapter extends BaseAdapter {
RepoStargazersAdapter.ViewHolder viewHolder; RepoStargazersAdapter.ViewHolder viewHolder;
if (finalView == null) { if (finalView == null) {
finalView = LayoutInflater.from(mCtx).inflate(R.layout.list_repo_stargazers, null); finalView = LayoutInflater.from(mCtx).inflate(R.layout.repo_stargazers_list, null);
viewHolder = new ViewHolder(finalView); viewHolder = new RepoStargazersAdapter.ViewHolder(finalView);
finalView.setTag(viewHolder); finalView.setTag(viewHolder);
} }
else { else {
@ -79,34 +77,13 @@ public class RepoStargazersAdapter extends BaseAdapter {
private void initData(RepoStargazersAdapter.ViewHolder viewHolder, int position) { private void initData(RepoStargazersAdapter.ViewHolder viewHolder, int position) {
UserInfo currentItem = stargazersList.get(position); UserInfo currentItem = stargazersList.get(position);
PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.memberAvatar); Picasso.get().load(currentItem.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(viewHolder.memberAvatar);
final TinyDB tinyDb = new TinyDB(mCtx);
Typeface myTypeface;
switch(tinyDb.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(mCtx.getAssets(), "fonts/manroperegular.ttf");
break;
}
if(!currentItem.getFullname().equals("")) { if(!currentItem.getFullname().equals("")) {
viewHolder.memberName.setText(currentItem.getFullname()); viewHolder.memberName.setText(currentItem.getFullname());
viewHolder.memberName.setTypeface(myTypeface);
} }
else { else {
viewHolder.memberName.setText(currentItem.getLogin()); viewHolder.memberName.setText(currentItem.getLogin());
viewHolder.memberName.setTypeface(myTypeface);
} }
} }

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