Compare commits

..

No commits in common. "master" and "v0.4.0" have entirely different histories.

415 changed files with 27151 additions and 50521 deletions

28
.circleci/config.yml Normal file
View File

@ -0,0 +1,28 @@
version: 2
jobs:
build:
docker:
- image: cirrusci/flutter:beta
branches:
only: master
steps:
- checkout
- run:
name: Run Flutter doctor
command: flutter doctor
- run:
name: Update package
command: flutter update-packages --force-upgrade
- run: echo $ENCODED_KEYSTORE | base64 -di > ${HOME}/keystore.jks
- run: echo 'export KEYSTORE=${HOME}/keystore.jks' >> $BASH_ENV
- run: dart tool/env.dart
- run:
name: Build the Android version
command: flutter build appbundle --no-shrink
- run:
name: Build the Android apk
command: flutter build apk --split-per-abi --no-shrink
- store_artifacts:
path: build/app/outputs/

12
.github/FUNDING.yml vendored
View File

@ -1,12 +0,0 @@
# These are supported funding model platforms
github: # Replace with up to 4buy-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: stonegate # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ["https://www.buymeacoffee.com/stonegate"] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@ -1,43 +0,0 @@
name: Flutter Build
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-java@v1
with:
java-version: "11.x"
- uses: subosito/flutter-action@v1
with:
channel: "stable" # 'dev', 'alpha', default to: 'stable'
- run: flutter pub get
- run: echo $ENCODED_KEYSTORE | base64 -di > android/app/keystore.jks
env:
ENCODED_KEYSTORE: ${{ secrets.ENCODED_KEYSTORE }}
- run: dart tool/env.dart
env:
API_KEY: ${{ secrets.API_KEY }}
PI_API_SECRET: ${{ secrets.PI_API_SECRET}}
PI_API_KEY: ${{ secrets.PI_API_KEY}}
- run: flutter build apk --split-per-abi --obfuscate --split-debug-info=debug/ --flavor=play
env:
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD}}
- run: flutter build appbundle --obfuscate --split-debug-info=debug/ --flavor=play
env:
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD}}
- uses: actions/upload-artifact@v2
with:
name: release-file
path: |
build/app/outputs/flutter-apk/*
build/app/outputs/bundle/playRelease/*

81
.gitignore vendored
View File

@ -1,41 +1,40 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
.vscode/settings.json
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/lib/.env.dart
/build/
pubspec.lock
analysis_options.yaml
.fvm/
# Web related
lib/generated_plugin_registrant.dart
# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/lib/.env.dart
/build/
pubspec.lock
.vscode
# Web related
lib/generated_plugin_registrant.dart
# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages

View File

@ -1,10 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 659dc8129d4edb9166e9a0d600439d135740933f
channel: beta
project_type: app
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 659dc8129d4edb9166e9a0d600439d135740933f
channel: beta
project_type: app

17
.vscode/launch.json vendored
View File

@ -1,17 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Flutter",
"request": "launch",
"type": "dart",
"args": [
"--flavor",
"play"
]
}
]
}

View File

@ -1,6 +0,0 @@
{
"cSpell.words": [
"cupertino",
"tsacdop"
]
}

View File

@ -1,433 +1,70 @@
# Tsacdop Changelog
## 0.6.0
Release date 2021/2/27
### New features
* Load local folder as playlist
* Option to always hide new mark for podcast.
* Memory use reduced a lot
* Add reddit link
## 0.5.9
Release date 2021/2/11
### Bug fix
* Some podcasts subscribe failed.
* Update fastlane screenshots.
## 0.5.8
Release date 2021/2/9
### New features
* Artwork shownotes and chapters in player panel.
* Play without subscription, inside search result directly.
### Bug fix
* Episode download failed with '/' in title.
## 0.5.7
Release date 2021/1.31
For frdoid
## 0.5.6
Release date 2021/1.28
### Bug fix
* Image saved wrongly after subscribe new podcast.
## 0.5.5
Release date 2021/1/25
### Bugs fix
* Position not saved after player stpoped.
* Wrongly remove episodes from playlist when get back from playlist page.
* Player crash on OP5T.
### Minor change
* Playlist page UI update.
## 0.5.4
Release date 2021/1/9
### New feature
* Support podcastindex namespace podcast:funding,
### Minor change
* Podcast detail page UI update.
### Bug fix
* Custom rss link subscribe error.
## 0.5.3
Release date 2021/1/7
### Minor change
* Option to open playlist page by default.
* Option to open podcast list page instead of group page.
* Add remove new mark buttong in podcast page.
## 0.5.2
Release date 2021/1/3
First release in 2021
### New features
* Custom playlist support.
* Playlist page redesign.
* Podcast detail page and group management page UI update.
* Add remove new mark button in recent tab antion bar.
* Support time setting in sleep mode.
### Minor change
* Remove add new to playlist button.
* Groups management perfomance improved.
* Podcast page opennning animation improved.
## 0.5.1
Release date 2020/11/1
### Bug fixed
* ListenNotes search error.
* Sync podcasts marked as never auto update.
* Download failed when network is busy.
### Minor change
* User can add episode to the top of playlist in popup menu.
* Show podcast name in episode detail page.
* Tap pocdast avatar in episode card to open podcast page.
## 0.5.0
Release date 2020/10/13
### New fewtures
* Support multi select on recent and favorite tab.
* Select all/ select before/ select after.
* Option to delete episode download file when played.
* OPtion to mark as listened after skipped.
### Bug fixed
* Feed pubdate parse error.
* Episodes load with initial position failed.
### Minor changes
* Single colume layout update.
* About page UI update.
* More smooth animation when open podcast detail page.
* Change sort by button style in podcast detail page.
* Auto rewind 3 seconds when resuming from paused state.
## 0.4.20
Release date 2020/10/3
### Bug fixed
* Rss feed parse error.
## 0.4.19
Release date 2020/10/1
### New features
* Set podcastindex as default search engine.
* Option to hide podcast discovery in search page.
* Italian translation support, thanks Edoardo.
### Bug fixed
* Mark all listened error.
## 0.4.18
Release date 2020/9/27
### New features
* Support gpodder.net sync.
* Portuguese translation, thanks Bruno.
* Turn off auto update for podcast.
* Pull to refresh in recent tab, supports group update.
### Minor changes
* Longpress 'see all' to open full podcast list.
## 0.4.17
Release date 2020/9/16
### Bug fixed
* Remove notification after app removed from recent.
## 0.4.16
Release date 2020/9/15
### New features
* Discovery feature in search page.
* Multi select in podcast page.
* Customize the speed options available.
### Bugs fixed
* Fix download error when podcast name includes /.
* Make the group name editable directly.
* Fixed shownote timestamp click error.
### Minor changes
* Update donate button UI.
## 0.4.15
Release date 2020/8/30
### New features
* Option to change notification panel layout.
* Option to change show notes font style.
* Option to hide listened default.
* Change skip next/previous to fastForward/rewind on headset click.
### Bugs fixed
* Download error when filename too long.
### Minor change
* Update download button style and downloaded indicator style.
* Add 1.1 to speed setting.
* Add 5s to skip seconds setting.
## 0.4.14
Release date 2020/8/20
Only for izzyonandroid.
## 0.4.13
Release date 2020/8/19
### Bugs fixed
* Downloaded episode play error, you might need to redownload the episode.
## 0.4.12
Release date 2020/8/15
### Bugs fixed
* Crash when reorder episodes or podcasts.
* Popup menu setting import bug.
* Default language failed to load.
### Minor changes
* Change language|feedback|podcast settings to button sheet.
* Add history in home playlist button.
* History page UI improved.
## 0.4.11
Release date 2020/8/12
### New features
* Boost volume. You can change boost level in settings.
* You can tap time stamp to skip instantly in shownote when the episode is playing.
* Add history list in playlist page.
* You can also mark not listened now.
### Minor change
* Improved time picker UI.
* Add episode setting page.
### Bugs fix
* Play record didn't saved after stop playing.
* Network error message didn't disapear after skip to next.
* Fireside avatar load error.
## 0.4.10
Release date 2020/8/6
### Bugs fixed
* Episdoe date parse error.
* Play from start after interrupt.
* Playlist in player unstable.
* Language setting not saved after restart app.
### Minor change
* Fast forward and rewind buttons UI changed.
## v0.4.9
Release date 2020/8/1
### New features
* Player UI redesign.
* Added player height setting.
* Added skip silence feature.
### Bugs fixed
* Language fixs. (Thanks to Atrate)
* Make app movable to SD card. (Thanks to Atrate)
### Minor change
* Episode page open animation improved.
* Podcast page load faster than before.
* Removed unnecessary scroll overlay effect.
* Episode page bottom menu hide when scroll down.
## v0.4.8
Release date 2020/7/25
### New features
* Filter in podcast detail page, you can also hide listened episodes.
* Search result ui improved, you can see more info for result.
* Update audio service to latest version.
* Support fast forward seconds and rewind seconds customize.
* Add Franch language support(beta).
* Add translators in about page.
### Bugs fixed
* Icon issue on below android 8 devices.
### Minor change
* Download button ui improved.
* Title changed to scrollable in episode detail page.
* Real dark theme improved.
* Add dot indicator in popup menu.
* Tap logo in homepage to toggle theme.
## v0.4.7
Release date 2020/7/18
### Bugs fixed
* Ompl files form other platform import error.
* Audio cache did't work.
## v0.4.6
Release date 2020/7/17
### Bugs fixed
* Mark listened not work.
* Recover subscribe wrong group.
## v0.4.5
Release date 2020/7/16
## New features
* OPML backup file supports group.
* Add settings backup and restore.
* Enable R8 and dart obfuscate.
## Bugs fixed
* OPML import not shown in group.
## Minor UI change
* Tap logo in homepage to toggle theme mode.
* Change subscribe button style.
* Improve history chart style.
## v0.4.0
Release date 2020/7/9
### New features
* Localization, changed all UI strings in app to support locale, support languages include en & zh right now.
* Changed episode popup menu UI, add a switch to tap to open popup men.
### Minor UI change
* Improve dropdown menu UI.
* Change icons color in setting page.
* Improve player panel animation.
* Add scroll bar in libraries page.
## v0.3.6
Release date 2020/6/30
### New feature
* Add sleep timer settings. include default time, auto start sleep timer, etc.
### Bug fixed
* Crash on stop player.
* Some download file didn't auto deleted.
## v0.3.5
Release date 2020/6/20
This is a energency release.
### Bugs fixed
* Crashed in download page or button after remove a podcast. Add episode check when load tasks from flutterdownloader.
### Minor UI change
* Add buy me a coffee in about page.
* Remove progress number in download list in failed task, change refresh icon color to red.
## v0.3.4
Release date 2020/6/16
### New Feature
* Support auto download new episodes, you can choose which podcast you want to auto download, you can also set if download using cellular data.
* Support auto delete downloaded episode, you can set days before delete.
* Support customize episode popup menu, you can add options you most want, **Like** | **Mark Listened** | **Download** newly added.
* Improved downloaded file manager, you can now sort downloads by date or size, you can also only view listened downloads.
### Minor UI Change
* Removed the listened indicator, increased the color difference for listened episodes.
* Add text in podcast manage page menu.
* Change episode shownote font to Martel.
### Bugs Fixed
* Auto play when receive notification.
* Lose podcast when import OMPL file.
### Other
* Add privacy policy.
# Tsacdop Changelog
## v0.4.0
Release date 2020/7/9
### New features
* Localization, changed all UI strings in app to support locale, support languages include en & zh right now.
* Changed episode popup menu UI, add a switch to tap to open popup men.
### Minor UI change
* Improve dropdown menu UI.
* Change icons color in setting page.
* Improve player panel animation.
* Add scroll bar in libraries page.
## v0.3.6
Release date 2020/6/30
### New feature
* Add sleep timer settings. include default time, auto start sleep timer, etc.
### Bug fixed
* Crash on stop player.
* Some download file didn't auto deleted.
## v0.3.5
Release date 2020/6/20
This is a energency release.
### Bugs fixed
* Crashed in download page or button after remove a podcast. Add episode check when load tasks from flutterdownloader.
### Minor UI change
* Add buy me a coffee in about page.
* Remove progress number in download list in failed task, change refresh icon color to red.
## v0.3.4
Release date 2020/6/16
### New Feature
* Support auto download new episodes, you can choose which podcast you want to auto download, you can also set if download using cellular data.
* Support auto delete downloaded episode, you can set days before delete.
* Support customize episode popup menu, you can add options you most want, **Like** | **Mark Listened** | **Download** newly added.
* Improved downloaded file manager, you can now sort downloads by date or size, you can also only view listened downloads.
### Minor UI Change
* Removed the listened indicator, increased the color difference for listened episodes.
* Add text in podcast manage page menu.
* Change episode shownote font to Martel.
### Bugs Fixed
* Auto play when receive notification.
* Lose podcast when import OMPL file.
### Other
* Add privacy policy.

1348
LICENSE

File diff suppressed because it is too large Load Diff

333
README.md
View File

@ -1,195 +1,138 @@
[![Tsacdop Banner][]][google play]
[![github action][]][github action link]
[![GitHub Release][]][github release - recent]
[![Github Downloads][]][github release - recent]
[![Localizely][]][localizely - website]
[![style: effective dart][]][effective dart pub]
[![License badge][]][license]
[![fdroid install][]][fdroid link]
## About
Enjoy podcasts with Tsacdop.
Tsacdop is a podcast player developed with Flutter, a clean, simply beautiful, and friendly app, which is also free and open source.
Credit to the Flutter team and all involved plugins, especially [webfeed](https://github.com/witochandra/webfeed), [Just_Audio](https://pub.dev/packages/just_audio), and [Provider](https://pub.dev/packages/provider).
The podcast search engine is powered by, [ListenNotes](https://listennotes.com) & [PodcastIndex](https://podcastindex.org/).
## Features
* Podcast group management
* Playlists support
* Sleep timer / speed setting
* OPML file export and import
* Auto-syncing in the background
* Listening and subscription history record
* Dark mode / accent color
* Download for offline play
* Auto-download new episodes / auto-delete outdated downloads
* Settings backup
* Skip silence
* Boost volume
More to come...
## Preview
| Home Page | Group | Podcast | Episode| Dark Mode |
| ----- | ----- | ----- | ------ | ----- |
|![][Homepage ScreenShot]|![][Group Screenshot] | ![][Podcast Screenshot] | ![][Episode Screenshot]| ![][Darkmode Screenshot] |
## Localization
Please [Email](mailto:<tsacdop.app@gmail.com>) me you'd like to contribute to support more languages!
Credit to [Localizely](https://localizely.com/) for kind support to open source projects.
### ![English]
### ![Chinese Simplified]
### ![French]
### ![Spanish]
### ![Portuguese]
## License
Tsacdop is licensed under the [GPL v3.0](https://github.com/stonega/tsacdop/blob/master/LICENSE) license.
## Build
1. If you don't have Flutter SDK installed; Please visit the official [Flutter][Flutter Install] site.
2. Fetch the latest source code from the master branch.
```
git clone https://github.com/stonega/tsacdop.git
```
3. Add api search api configure file.
Tsacdop uses the ListenNotes API 1.0 pro to search for podcasts, which is not free, so I can not expose the API key in the repo.
If you want to build the app, you need to create a new file named `.env.dart` in the lib folder. Add the following code to `.env.dart`. If you don't have a ListenNotes api key, keep the apiKey empty like ''. Then the app will only support the PodcastIndex search.
You can get your own ListenNotes API key on [ListenNotes](https://www.listennotes.com/api/). Remember that you need to get a pro plan API because the basic plan doesn't provide an rss link for the search result.
``` dart
final environment = {"apiKey":""};
```
4. Run the app with Android Studio or Visual Studio. Or the command line.
```
flutter pub get
flutter run
```
## Contribute
If you have an issue or found a bug, please raise a GitHub issue. Pull requests are also welcome.
## Architecture
### Plugins
* Local storage
+ sqflite
+ shared_preferences
* Audio
+ just_audio
+ audio_service
* State management
+ provider
* Download
+ flutter_downloader
* Background task
+ workmanager
### Directory Structure
```
UI
src
└──home
├──home.dart [Homepage]
├──searc_podcast.dart [Search Page]
└──playlist.dart [Playlist Page]
└──podcasts
├──podcast_manage.dart [Group Page]
└──podcast_detail.dart [Podcast Page]
└──episodes
└──episode_detail.dart [Episode Page]
└──settings
└──setting.dart [Setting Page]
STATE
src
└──state
├──audio_state.dart [Audio State]
├──download_state.dart [Episode Download]
├──podcast_group.dart [Podcast Groups]
├──refresh_podcast.dart [Episode Refresh]
└──setting_state.dart [Setting]
Service
src
└──service
├──api_service.dart [Podcast Search]
├──gpodder_api.dart [Gpodder intergate]
└──ompl_builde.dart [OMPL export]
```
## Known Issue
* Playlist is unstable
## Contact
You can reach out to me directly at [tsacdop.app@gmail.com](mailto:<tsacdop.app@gmail.com>).
Or you can join our [Telegram Group](https://t.me/joinchat/Bk3LkRpTHy40QYC78PK7Qg).
## Getting Started with Flutter
This project is a starting point for a Flutter application.
Here are a few resources to get you started if this is your first Flutter project:
* [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
* [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials, samples, guidance on mobile development, and a full API reference.
[Flutter Install]: https://flutter.dev/docs/get-started/install
[tsacdop banner]: https://raw.githubusercontent.com/stonega/tsacdop/master/preview/banner.png
[build status - cirrus]: https://circleci.com/gh/stonega/tsacdop/tree/master.svg?style=shield
[github action]: https://github.com/stonega/tsacdop/workflows/Flutter%20Build/badge.svg
[github action link]: https://github.com/stonega/tsacdop/actions
[build status ]: https://circleci.com/gh/stonega/tsacdop/tree/master
[github release]: https://img.shields.io/github/v/release/stonega/tsacdop
[github release - recent]: https://github.com/stonega/tsacdop/releases
[github downloads]: https://img.shields.io/github/downloads/stonega/tsacdop/total?color=%230000d&label=downloads
[fdroid install]: https://img.shields.io/f-droid/v/com.stonegate.tsacdop?include_prereleases
[fdroid link]: https://f-droid.org/en/packages/com.stonegate.tsacdop/
[localizely]: https://img.shields.io/badge/dynamic/json?color=%2326c6da&label=localizely&query=%24.languages.length&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus
[English]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=English&query=%24.languages%5B3%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
[Chinese Simplified]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=Chinese%20Simplified&query=%24.languages%5B2%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
[French]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=French(ppp)&query=%24.languages%5B5%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
[Spanish]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=Spanish(Joel)&query=%24.languages%5B7%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
[Portuguese]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=portuguese(Bruno)&query=%24.languages%5B9%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
[localizely - website]: https://localizely.com/
[google play - icon]: https://img.shields.io/badge/google-playStore-%2323CCC6
[google play]: https://play.google.com/store/apps/details?id=com.stonegate.tsacdop
[Homepage ScreenShot]: https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893838840.png
[Group Screenshot]: https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585894051734.png
[Podcast Screenshot]: https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893877702.png
[Episode Screenshot]: https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585896237809.png
[Darkmode Screenshot]: https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893920721.png
[style: effective dart]: https://img.shields.io/badge/style-effective_dart-40c4ff.svg
[effective dart pub]: https://pub.dev/packages/effective_dart
[license]: https://github.com/stonega/tsacdop/blob/master/LICENSE
[License badge]: https://img.shields.io/badge/license-GPLv3-yellow.svg
<p align="center">
<img src="https://raw.githubusercontent.com/stonega/tsacdop/master/android/app/src/main/res/mipmap-xhdpi/ic_notification.png" art = "Logo"/>
</br>
<img src="https://raw.githubusercontent.com/stonega/tsacdop/master/android/app/src/main/res/mipmap-xhdpi/text.png" art = "Tsacdop"/>
</p>
[![Build Status - Cirrus][]][Build status]
[![GitHub Release][]][Github Release - Recent]
[![Github Downloads][]][Github Release - Recent]
[![Localizely][]][Localizely - Website]
[![Google Play - Icon][]][Google Play]
## About
Enjoy podcasts with Tsacdop.
Tsacdop is a podcast player developed with flutter, a clean, simply beautiful and friendly app, and is free and opensource.
Credit to flutter team and all involved plugins, especially [webfeed](https://github.com/witochandra/webfeed) and [Just_Audio](https://pub.dev/packages/just_audio).
The podcasts search engine is powered by [ListenNotes](https://listennotes.com).
## Features
* Podcasts group management
* Playlist support
* Sleep timer / Speed setting
* OMPL file export and import
* Auto syncing in background
* Listen and subscribe history record
* Dark mode / Accent color
* Download for offline playing
* Auto download new episodes / Auto delete outdated downloads
More to come...
## Preview
| HomePage | Group | Podcast | Episode | DarkMode |
| ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893838840.png" art = "HomePage"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585894051734.png" art = "Groups"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893877702.png" art = "Podcast"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585896237809.png" art = "Episode"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893920721.png" art = "DarkMode"/> |
## Localization
Support languages
* English
* Chinese Simplified (beta)
Please [Email](mailto:<tsacdop.app@gmail.com>) me you'd like to contribute to support more languages!
Credit to [Localizely](https://localizely.com/) for kind support to open source project.
## License
Tsacdop is licensed under the [GPL V3.0](https://github.com/stonega/tsacdop/blob/master/LICENSE) license.
## Build
Tsacdop is using ListenNotes api 1.0 pro to search podcast, which is not free. So I can not expose the api key in the repo.
If you want to build the app, you need to create a new file named .env.dart in lib folder. Add below code in .env.dart.
``` dart
final environment = {"apiKey":"APIKEY"};
```
You can get own api key on [ListenNotes](https://www.listennotes.com/api/), basic plan is free to all, and replace "APIKEY" with it.
If no api key added, the search function in the app won't work. But you can still add podcasts by serach rss link or import ompl file.
## Archetecture
### Plugins
* Local storage
- sqflite
- shared_preferences
* Audio
- just_audio
- audio_service
* State management
- provider
* Download
- flutter_downloader
### Directory Structure
```
UI
src
├──home
├──home.dart [Homepage]
├──addpodcast.dart [Search Page]
├──playlist.dart [Playlist Page]
├──podcasts
├──podcast_manage.dart [Group Page]
├──podcast_detail.dart [Podcast Page]
├──episodes
├──episode_detail.dart [Episode Page]
├──settings
├──setting.dart [Setting Page]
STATES
src
├──state
├──audio_state.dart [Audio State]
├──download_state.dart [Episode Download]
├──podcast_group.dart [Podcast Groups]
├──refresh_podcast.dart [Episode Refresh]
├──setting_state.dart [Setting]
├──subscribe_podcast.dart [Podcast Subscribe]
```
## Known Issue
* Playlist unstable
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
* [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
* [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials, samples, guidance on mobile development, and a full API reference.
[Build Status - Cirrus]: https://circleci.com/gh/stonega/tsacdop/tree/master.svg?style=shield
[Build status]: https://circleci.com/gh/stonega/tsacdop/tree/master
[Github Release]: https://img.shields.io/github/v/release/stonega/tsacdop
[Github Release - Recent]: https://github.com/stonega/tsacdop/releases
[Github Downloads]: https://img.shields.io/github/downloads/stonega/tsacdop/total?color=%230000d&label=downloads
[Localizely]: https://img.shields.io/badge/dynamic/json?color=%2326c6da&label=localizely&query=%24.languages.length&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus
[Localizely - Website]: https://localizely.com/
[Google Play - Icon]: https://img.shields.io/badge/google-playStore-%2323CCC6
[Google Play]: https://play.google.com/store/apps/details?id=com.stonegate.tsacdop

14
android/.gitignore vendored
View File

@ -1,7 +1,7 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java

View File

@ -1,28 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>android</name>
<comment>Project android created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1651309616208</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>android</name>
<comment>Project android created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@ -1,13 +1,13 @@
arguments=
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=/usr/lib/jvm/java-17-openjdk-17.0.3.0.7-1.fc36.x86_64
jvm.arguments=
offline.mode=false
override.workspace.settings=true
show.console.view=true
show.executions.view=true
arguments=
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
connection.project.dir=app
eclipse.preferences.version=1
gradle.user.home=
java.home=C\:/Program Files/Java/jdk1.8.0_171
jvm.arguments=
offline.mode=false
override.workspace.settings=true
show.console.view=true
show.executions.view=true

View File

@ -1,3 +0,0 @@
source "https://rubygems.org"
gem "fastlane"

View File

@ -1,201 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.3)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.1.0)
aws-partitions (1.422.0)
aws-sdk-core (3.111.2)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.41.0)
aws-sdk-core (~> 3, >= 3.109.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.87.0)
aws-sdk-core (~> 3, >= 3.109.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.2)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.0.3)
colored (1.2)
colored2 (3.1.2)
commander-fastlane (4.4.6)
highline (~> 1.7.2)
declarative (0.0.20)
declarative-option (0.1.0)
digest-crc (0.6.3)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
emoji_regex (3.2.1)
excon (0.78.1)
faraday (1.3.0)
faraday-net_http (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday-net_http (1.0.1)
faraday_middleware (1.0.0)
faraday (~> 1.0)
fastimage (2.2.2)
fastlane (2.172.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored
commander-fastlane (>= 4.4.6, < 5.0.0)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.37.0, < 0.39.0)
google-cloud-storage (>= 1.15.0, < 2.0.0)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3)
google-api-client (0.38.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.9)
httpclient (>= 2.8.1, < 3.0)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.12)
google-apis-core (0.2.1)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.14)
httpclient (>= 2.8.1, < 3.0)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
rexml
signet (~> 0.14)
webrick
google-apis-iamcredentials_v1 (0.1.0)
google-apis-core (~> 0.1)
google-apis-storage_v1 (0.1.0)
google-apis-core (~> 0.1)
google-cloud-core (1.5.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.4.0)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.0.1)
google-cloud-storage (1.30.0)
addressable (~> 2.5)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.1)
google-cloud-core (~> 1.2)
googleauth (~> 0.9)
mini_mime (~> 1.0)
googleauth (0.15.0)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.14)
highline (1.7.10)
http-cookie (1.0.3)
domain_name (~> 0.5)
httpclient (2.8.3)
jmespath (1.6.1)
json (2.5.1)
jwt (2.2.2)
memoist (0.16.2)
mini_magick (4.11.0)
mini_mime (1.0.2)
multi_json (1.15.0)
multipart-post (2.0.0)
nanaimo (0.3.0)
naturally (2.2.1)
os (1.1.1)
plist (3.6.0)
public_suffix (4.0.6)
rake (13.0.3)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.2.5)
rouge (2.0.7)
ruby2_keywords (0.0.4)
rubyzip (2.3.0)
security (0.1.3)
signet (0.14.1)
addressable (~> 2.3)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.8)
CFPropertyList
naturally
slack-notifier (2.3.2)
terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
tty-cursor (0.7.1)
tty-screen (0.8.1)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
webrick (1.7.0)
word_wrap (1.0.0)
xcodeproj (1.19.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
x86_64-linux
DEPENDENCIES
fastlane
BUNDLED WITH
2.2.7

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>

View File

@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>app</name>
<comment>Project app created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>app</name>
<comment>Project app created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@ -1,13 +1,13 @@
arguments=
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(6.3))
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=C\:/Program Files/Java/jdk1.8.0_171
jvm.arguments=
offline.mode=false
override.workspace.settings=true
show.console.view=true
show.executions.view=true
arguments=
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(6.3))
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=C\:/Program Files/Java/jdk1.8.0_171
jvm.arguments=
offline.mode=false
override.workspace.settings=true
show.console.view=true
show.executions.view=true

View File

@ -1,4 +1,4 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.source=1.8
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.source=1.8

View File

@ -1,110 +1,90 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 31
ndkVersion "22.1.7171670"
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
checkReleaseBuilds false
}
defaultConfig {
applicationId "com.stonegate.tsacdop"
minSdkVersion 21
targetSdkVersion 29
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
signingConfigs {
release {
storeFile file(System.getenv("KEYSTORE") ?:"keystore.jks")
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
// keyAlias keystoreProperties['keyAlias']
// keyPassword keystoreProperties['keyPassword']
// storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
// storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
shrinkResources false
}
}
flavorDimensions "deploy"
productFlavors {
play {
dimension "deploy"
signingConfig signingConfigs.release
}
fdroid {
dimension "deploy"
signingConfig null
}
}
// android.applicationVariants.all { variant ->
// if (variant.flavorName == "play") {
// variant.outputs.all { output ->
// output.outputFileName = "app-release.apk"
// }
// }
// }
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
def appcompat_version = "1.1.0"
implementation "androidx.appcompat:appcompat:$appcompat_version"
implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 29
ndkVersion "21.1.6352462"
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.stonegate.tsacdop"
minSdkVersion 19
targetSdkVersion 29
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
signingConfigs {
release {
storeFile file(System.getenv("KEYSTORE") ?:"keystore.jks")
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
// keyAlias keystoreProperties['keyAlias']
// keyPassword keystoreProperties['keyPassword']
// storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
// storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
shrinkResources false
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
def appcompat_version = "1.1.0"
implementation "androidx.appcompat:appcompat:$appcompat_version"
implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
}

View File

@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.stonegate.tsacdop">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.stonegate.tsacdop">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -1,33 +1,38 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.stonegate.tsacdop" xmlns:tools="http://schemas.android.com/tools" android:installLocation="auto">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application android:name=".MainApplication" android:label="Tsacdop" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="com.ryanheise.audioservice.AudioServiceActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/LaunchTheme" />
<meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/normal_background" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.ryanheise.audioservice.AudioService">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
<receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data android:name="flutterEmbedding" android:value="2" />
</application>
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.stonegate.tsacdop"
xmlns:tools="http://schemas.android.com/tools">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application android:name="io.flutter.app.FlutterApplication" android:label="Tsacdop" android:icon="@mipmap/ic_launcher_icon" android:roundIcon="@mipmap/ic_launcher_round" android:networkSecurityConfig="@xml/network_security_config">
<activity android:name=".MainActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/LaunchTheme" />
<meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/normal_background" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- <meta-data android:name="io.flutter.embedding.android.SplashScreenUntilFirstFrame" android:value="true" /> -->
</activity>
<service android:name="com.ryanheise.audioservice.AudioService">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</service>
<receiver android:name="androidx.media.session.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data android:name="flutterEmbedding" android:value="2" />
</application>
</manifest>

View File

@ -1,45 +1,39 @@
package io.flutter.plugins;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import io.flutter.Log;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.pathprovider.PathProviderPlugin;
import com.tekartik.sqflite.SqflitePlugin;
import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin;
import vn.hunghd.flutterdownloader.FlutterDownloaderPlugin;
@Keep
public final class IsolatePluginRegistrant {
private static final String TAG = "CustomPluginRegistrant";
public static void registerWith(@NonNull FlutterEngine flutterEngine) {
try {
flutterEngine.getPlugins().add(new vn.hunghd.flutterdownloader.FlutterDownloaderPlugin());
} catch(Exception e) {
Log.e(TAG, "Error registering plugin flutter_downloader, vn.hunghd.flutterdownloader.FlutterDownloaderPlugin", e);
}
try {
flutterEngine.getPlugins().add(new com.rmawatson.flutterisolate.FlutterIsolatePlugin());
} catch(Exception e) {
Log.e(TAG, "Error registering plugin flutter_isolate, com.rmawatson.flutterisolate.FlutterIsolatePlugin", e);
}
try {
flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin());
} catch(Exception e) {
Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e);
}
try {
flutterEngine.getPlugins().add(new io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin());
} catch(Exception e) {
Log.e(TAG, "Error registering plugin shared_preferences, io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin", e);
}
try {
flutterEngine.getPlugins().add(new com.tekartik.sqflite.SqflitePlugin());
} catch(Exception e) {
Log.e(TAG, "Error registering plugin sqflite, com.tekartik.sqflite.SqflitePlugin", e);
}
}
package io.flutter.plugins;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.pathprovider.PathProviderPlugin;
import com.tekartik.sqflite.SqflitePlugin;
import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin;
import vn.hunghd.flutterdownloader.FlutterDownloaderPlugin;
/**
* Generated file. Do not edit. This file is generated by the Flutter tool based
* on the plugins that support the Android platform.
*/
@Keep
public final class IsolatePluginRegistrant {
public static void registerWith(PluginRegistry registry) {
if (alreadyRegisteredWith(registry)) {
return;
}
PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"));
SqflitePlugin.registerWith(registry.registrarFor("com.tekartik.sqflite.SqflitePlugin"));
SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin"));
FlutterDownloaderPlugin.registerWith(registry.registrarFor("vn.hunghd.flutterdownloader.FlutterDownloaderPlugin"));
}
private static boolean alreadyRegisteredWith(PluginRegistry registry) {
final String key = IsolatePluginRegistrant.class.getCanonicalName();
if (registry.hasPlugin(key)) {
return true;
}
registry.registrarFor(key);
return false;
}
}

View File

@ -1,28 +1,28 @@
package com.stonegate.tsacdop
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.view.FlutterNativeView
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.plugins.IsolatePluginRegistrant
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.embedding.engine.dart.DartExecutor
import io.flutter.embedding.engine.dart.DartExecutor.DartCallback
import com.rmawatson.flutterisolate.FlutterIsolatePlugin
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
MethodChannel(flutterEngine.dartExecutor, "android_app_retain").apply {
setMethodCallHandler { method, result ->
if (method.method == "sendToBackground") {
moveTaskToBack(true)
}
}
}
}
}
package com.stonegate.tsacdop
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.view.FlutterNativeView
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.plugins.IsolatePluginRegistrant
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.embedding.engine.dart.DartExecutor
import io.flutter.embedding.engine.dart.DartExecutor.DartCallback
import com.rmawatson.flutterisolate.FlutterIsolatePlugin
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
FlutterIsolatePlugin.setCustomIsolateRegistrant(IsolatePluginRegistrant::class.java);
MethodChannel(flutterEngine.dartExecutor, "android_app_retain").apply {
setMethodCallHandler { method, result ->
if (method.method == "sendToBackground") {
moveTaskToBack(true)
}
}
}
}
}

View File

@ -1,10 +0,0 @@
package com.stonegate.tsacdop
import com.rmawatson.flutterisolate.FlutterIsolatePlugin
import io.flutter.app.FlutterApplication
import io.flutter.plugins.IsolatePluginRegistrant
public class MainApplication: FlutterApplication() {
public fun MainApplication() {
FlutterIsolatePlugin.setCustomIsolateRegistrant(IsolatePluginRegistrant::class.java);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 559 B

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 909 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 B

After

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 729 B

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 882 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 B

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 578 B

After

Width:  |  Height:  |  Size: 649 B

View File

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blackGrey" />
<!-- You can insert your own image assets here -->
<item>
<bitmap
android:gravity="center"
android:tileMode="disabled"
android:src="@mipmap/ic_splash" />
</item>
<item android:bottom="100dp">
<bitmap
android:gravity="bottom"
android:src="@mipmap/text_light" />
</item>
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blackGrey" />
<!-- You can insert your own image assets here -->
<item>
<bitmap
android:gravity="center"
android:tileMode="disabled"
android:src="@mipmap/ic_splash" />
</item>
<item android:bottom="100dp">
<bitmap
android:gravity="bottom"
android:src="@mipmap/text_light" />
</item>
</layer-list>

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blackGrey" />
<!-- You can insert your own image assets here -->
<item android:bottom="100dp">
<bitmap android:gravity="bottom" android:src="@mipmap/text_light" />
</item>-->
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blackGrey" />
<!-- You can insert your own image assets here -->
<item android:bottom="100dp">
<bitmap android:gravity="bottom" android:src="@mipmap/text_light" />
</item>-->
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 521 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 593 B

After

Width:  |  Height:  |  Size: 758 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 966 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 692 B

After

Width:  |  Height:  |  Size: 989 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 771 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 918 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 395 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 865 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 521 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 880 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 926 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<item>
<bitmap android:gravity="center" android:tileMode="disabled" android:src="@mipmap/ic_splash" />
</item>
<item android:bottom="100dp">
<bitmap android:gravity="bottom" android:src="@mipmap/text" />
</item>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<item>
<bitmap android:gravity="center" android:tileMode="disabled" android:src="@mipmap/ic_splash" />
</item>
<item android:bottom="100dp">
<bitmap android:gravity="bottom" android:src="@mipmap/text" />
</item>
</layer-list>

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blackGrey" />
<!-- You can insert your own image assets here -->
<item>
<bitmap android:gravity="center" android:tileMode="disabled" android:src="@mipmap/ic_splash" />
</item>
<item android:bottom="100dp">
<bitmap android:gravity="bottom" android:src="@mipmap/text_light" />
</item>
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blackGrey" />
<!-- You can insert your own image assets here -->
<item>
<bitmap android:gravity="center" android:tileMode="disabled" android:src="@mipmap/ic_splash" />
</item>
<item android:bottom="100dp">
<bitmap android:gravity="bottom" android:src="@mipmap/text_light" />
</item>
</layer-list>

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<item android:bottom="100dp">
<bitmap android:gravity="bottom" android:src="@mipmap/text_light" />
</item>
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<item android:bottom="100dp">
<bitmap android:gravity="bottom" android:src="@mipmap/text_light" />
</item>
</layer-list>

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blackGrey" />
<!-- You can insert your own image assets here -->
<item android:bottom="100dp">
<bitmap android:gravity="bottom" android:src="@mipmap/text_light" />
</item>
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blackGrey" />
<!-- You can insert your own image assets here -->
<item android:bottom="100dp">
<bitmap android:gravity="bottom" android:src="@mipmap/text_light" />
</item>
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

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