├── .gitignore
├── Flym.iml
├── LICENSE
├── LICENSE_GPLv3
├── README.md
├── app
├── build.gradle
├── proguard-rules.pro
├── schemas
│ └── org.decsync.flym.data.AppDatabase
│ │ ├── 1.json
│ │ ├── 2.json
│ │ ├── 3.json
│ │ └── 4.json
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-playstore.png
│ ├── java
│ │ └── org
│ │ │ └── decsync
│ │ │ └── flym
│ │ │ ├── App.kt
│ │ │ ├── MyAppGlideModule.kt
│ │ │ ├── data
│ │ │ ├── AppDatabase.kt
│ │ │ ├── converters
│ │ │ │ └── Converters.kt
│ │ │ ├── dao
│ │ │ │ ├── EntryDao.kt
│ │ │ │ ├── FeedDao.kt
│ │ │ │ └── TaskDao.kt
│ │ │ ├── entities
│ │ │ │ ├── DecsyncArticle.kt
│ │ │ │ ├── DecsyncFeed.kt
│ │ │ │ ├── Entry.kt
│ │ │ │ ├── EntryWithFeed.kt
│ │ │ │ ├── Feed.kt
│ │ │ │ ├── FeedWithCount.kt
│ │ │ │ ├── SearchFeedResult.kt
│ │ │ │ └── Task.kt
│ │ │ └── utils
│ │ │ │ └── PrefConstants.kt
│ │ │ ├── service
│ │ │ ├── AutoRefreshJobService.kt
│ │ │ └── FetcherService.kt
│ │ │ ├── ui
│ │ │ ├── about
│ │ │ │ └── AboutActivity.kt
│ │ │ ├── discover
│ │ │ │ ├── DiscoverActivity.kt
│ │ │ │ ├── DiscoverFragment.kt
│ │ │ │ ├── FeedManagementInterface.kt
│ │ │ │ ├── FeedSearchFragment.kt
│ │ │ │ └── SquareGridItemLayout.kt
│ │ │ ├── entries
│ │ │ │ ├── EntriesFragment.kt
│ │ │ │ └── EntryAdapter.kt
│ │ │ ├── entrydetails
│ │ │ │ ├── EntryDetailsActivity.kt
│ │ │ │ ├── EntryDetailsFragment.kt
│ │ │ │ └── EntryDetailsView.kt
│ │ │ ├── feeds
│ │ │ │ ├── BaseFeedAdapter.kt
│ │ │ │ ├── DrawerFeedAdapter.kt
│ │ │ │ ├── EditFeedAdapter.kt
│ │ │ │ ├── FeedGroup.kt
│ │ │ │ ├── FeedListEditActivity.kt
│ │ │ │ └── FeedListEditFragment.kt
│ │ │ ├── intro
│ │ │ │ ├── IntroActivity.kt
│ │ │ │ └── SafUpdateActivity.kt
│ │ │ ├── main
│ │ │ │ ├── ContainersLayout.kt
│ │ │ │ ├── MainActivity.kt
│ │ │ │ └── MainNavigator.kt
│ │ │ ├── settings
│ │ │ │ ├── SettingsActivity.kt
│ │ │ │ └── SettingsFragment.kt
│ │ │ └── views
│ │ │ │ ├── AutoSummaryListPreference.kt
│ │ │ │ ├── BakedBezierInterpolator.java
│ │ │ │ ├── DragNDropListener.kt
│ │ │ │ ├── DragNDropRecyclerView.kt
│ │ │ │ ├── EmptyRecyclerView.kt
│ │ │ │ ├── SwipeProgressBar.java
│ │ │ │ └── SwipeRefreshLayout.java
│ │ │ └── utils
│ │ │ ├── ActivityExtensions.kt
│ │ │ ├── ContextExtensions.kt
│ │ │ ├── DecsyncListeners.kt
│ │ │ ├── DecsyncUtils.kt
│ │ │ ├── HtmlUtils.kt
│ │ │ ├── StringExtensions.kt
│ │ │ └── ViewExtensions.kt
│ └── res
│ │ ├── anim
│ │ ├── grid_layout_animation_from_bottom.xml
│ │ └── item_animation_from_bottom.xml
│ │ ├── animator
│ │ └── appbar_always_elevated.xml
│ │ ├── color
│ │ ├── bottom_navigation_item.xml
│ │ ├── colored_read_state.xml
│ │ ├── colored_read_state_black.xml
│ │ ├── colored_read_state_light.xml
│ │ ├── read_state.xml
│ │ ├── read_state_black.xml
│ │ └── read_state_light.xml
│ │ ├── drawable-nodpi
│ │ └── header_background.png
│ │ ├── drawable-w840dp
│ │ └── selected_item_background.xml
│ │ ├── drawable-xhdpi
│ │ ├── folder.xml
│ │ └── ic_statusbar_rss.png
│ │ ├── drawable
│ │ ├── ic_add_white_24dp.xml
│ │ ├── ic_all_green_108dp.xml
│ │ ├── ic_all_white_24dp.xml
│ │ ├── ic_back_white_24dp.xml
│ │ ├── ic_baseline_add_24.xml
│ │ ├── ic_baseline_check_24.xml
│ │ ├── ic_create_new_folder_white_24dp.xml
│ │ ├── ic_drag_handle_white_24dp.xml
│ │ ├── ic_empty_gray_100dp.xml
│ │ ├── ic_fulltext_white_24dp.xml
│ │ ├── ic_keyboard_arrow_down_black_24dp.xml
│ │ ├── ic_keyboard_arrow_down_white_24dp.xml
│ │ ├── ic_keyboard_arrow_up_black_24dp.xml
│ │ ├── ic_keyboard_arrow_up_white_24dp.xml
│ │ ├── ic_launcher_foreground.xml
│ │ ├── ic_list_black_24dp.xml
│ │ ├── ic_list_white_24dp.xml
│ │ ├── ic_menu_24dp.xml
│ │ ├── ic_menu_red_highlight_24dp.xml
│ │ ├── ic_more_vert_white_24dp.xml
│ │ ├── ic_navigate_before_black_24dp.xml
│ │ ├── ic_navigate_before_white_24dp.xml
│ │ ├── ic_navigate_next_black_24dp.xml
│ │ ├── ic_navigate_next_white_24dp.xml
│ │ ├── ic_open_in_browser_white_24dp.xml
│ │ ├── ic_original_text_white_24dp.xml
│ │ ├── ic_read_all_white_24dp.xml
│ │ ├── ic_search_white_24dp.xml
│ │ ├── ic_share_white_24dp.xml
│ │ ├── ic_star_24dp.xml
│ │ ├── ic_star_border_24dp.xml
│ │ ├── ic_star_border_white_24dp.xml
│ │ ├── ic_star_green_108dp.xml
│ │ ├── ic_star_white_24dp.xml
│ │ ├── ic_unread_green_108dp.xml
│ │ ├── ic_unread_white_24dp.xml
│ │ ├── selected_feed_background.xml
│ │ └── selected_item_background.xml
│ │ ├── layout-w840dp
│ │ └── view_main_containers.xml
│ │ ├── layout
│ │ ├── activity_feed_list_edit.xml
│ │ ├── activity_feed_search.xml
│ │ ├── activity_intro_directory.xml
│ │ ├── activity_intro_welcome.xml
│ │ ├── activity_main.xml
│ │ ├── activity_saf_update.xml
│ │ ├── activity_settings.xml
│ │ ├── dialog_edit_feed.xml
│ │ ├── fragment_discover.xml
│ │ ├── fragment_entries.xml
│ │ ├── fragment_entry_details.xml
│ │ ├── fragment_entry_details_noswipe.xml
│ │ ├── fragment_feed_list_edit.xml
│ │ ├── fragment_feed_search.xml
│ │ ├── item_discover_topic.xml
│ │ ├── item_feed_search_result.xml
│ │ ├── view_entry.xml
│ │ ├── view_feed.xml
│ │ ├── view_feed_edit.xml
│ │ ├── view_main_containers.xml
│ │ └── view_main_drawer_header.xml
│ │ ├── menu
│ │ ├── menu_bottom_navigation_items.xml
│ │ ├── menu_drawer_feed.xml
│ │ ├── menu_drawer_header.xml
│ │ ├── menu_fragment_entries.xml
│ │ ├── menu_fragment_entry_details.xml
│ │ └── menu_fragment_feed_list_edit.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_all.xml
│ │ ├── ic_favorites.xml
│ │ ├── ic_launcher.xml
│ │ ├── ic_launcher_round.xml
│ │ └── ic_unreads.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_all.png
│ │ ├── ic_favorites.png
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_unreads.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_all.png
│ │ ├── ic_favorites.png
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_unreads.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_all.png
│ │ ├── ic_favorites.png
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_unreads.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_all.png
│ │ ├── ic_favorites.png
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_unreads.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_all.png
│ │ ├── ic_favorites.png
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_unreads.png
│ │ ├── values-af
│ │ └── strings.xml
│ │ ├── values-ar
│ │ └── strings.xml
│ │ ├── values-b+pt+BR
│ │ └── strings.xml
│ │ ├── values-b+sr+Latn
│ │ └── strings.xml
│ │ ├── values-b+zh+TW
│ │ └── strings.xml
│ │ ├── values-bn
│ │ └── strings.xml
│ │ ├── values-ca
│ │ └── strings.xml
│ │ ├── values-cs
│ │ └── strings.xml
│ │ ├── values-da
│ │ └── strings.xml
│ │ ├── values-de
│ │ └── strings.xml
│ │ ├── values-el
│ │ └── strings.xml
│ │ ├── values-es
│ │ └── strings.xml
│ │ ├── values-eu
│ │ └── strings.xml
│ │ ├── values-fi
│ │ └── strings.xml
│ │ ├── values-fr
│ │ └── strings.xml
│ │ ├── values-he
│ │ └── strings.xml
│ │ ├── values-hu
│ │ └── strings.xml
│ │ ├── values-in
│ │ └── strings.xml
│ │ ├── values-it
│ │ └── strings.xml
│ │ ├── values-ja
│ │ └── strings.xml
│ │ ├── values-ko
│ │ └── strings.xml
│ │ ├── values-nl
│ │ └── strings.xml
│ │ ├── values-no
│ │ └── strings.xml
│ │ ├── values-pl
│ │ └── strings.xml
│ │ ├── values-pt
│ │ └── strings.xml
│ │ ├── values-ro
│ │ └── strings.xml
│ │ ├── values-ru
│ │ └── strings.xml
│ │ ├── values-sk
│ │ └── strings.xml
│ │ ├── values-sr
│ │ └── strings.xml
│ │ ├── values-sv
│ │ └── strings.xml
│ │ ├── values-tr
│ │ └── strings.xml
│ │ ├── values-uk
│ │ └── strings.xml
│ │ ├── values-vi
│ │ └── strings.xml
│ │ ├── values-w376dp
│ │ └── dimens.xml
│ │ ├── values-w600dp
│ │ └── integers.xml
│ │ ├── values-w840dp
│ │ ├── dimens.xml
│ │ └── styles.xml
│ │ ├── values-zh
│ │ └── strings.xml
│ │ ├── values
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── integers.xml
│ │ ├── not_translatable_strings.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ │ ├── xml-v25
│ │ └── shortcuts.xml
│ │ └── xml
│ │ ├── file_paths.xml
│ │ ├── network_security_config.xml
│ │ ├── settings.xml
│ │ └── shortcuts.xml
│ └── test
│ └── java
│ └── org
│ └── decsync
│ └── flym
│ └── data
│ └── entities
│ └── FeedTest.kt
├── build.gradle
├── crowdin.yml
├── fastlane
└── metadata
│ └── android
│ └── en-US
│ ├── changelogs
│ ├── 41.txt
│ ├── 43.txt
│ ├── 44.txt
│ ├── 45.txt
│ └── 46.txt
│ ├── full_description.txt
│ ├── images
│ ├── featureGraphic.jpg
│ ├── icon.png
│ ├── phoneScreenshots
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ └── 4.png
│ └── sevenInchScreenshots
│ │ └── 1.png
│ ├── short_description.txt
│ └── title.txt
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── graphics
├── flame.svg
├── logo.svg
├── status_icon.svg
└── white_flame.png
├── lint.xml
├── settings.gradle
└── tools
└── flym_v1_to_v2.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS junk files
2 | [Tt]humbs.db
3 | *.DS_Store
4 |
5 | # Built application files
6 | *.apk
7 | *.ap_
8 |
9 | # Files for the dex VM
10 | *.dex
11 |
12 | # Java class files
13 | *.class
14 |
15 | # Generated files
16 | bin/
17 | gen/
18 | proguard/
19 |
20 | # Local configuration file (sdk path, keystore, etc)
21 | local.properties
22 |
23 | # IDE project files
24 | .idea/
25 | .gradle/
26 | .settings/
27 | .metadata
28 | .externalNativeBuild
29 | build
30 | captures
31 | *.log
32 | *.iml
33 |
34 | # Junk generated by editors
35 | *~
36 | *.swp
37 | *.bak
38 |
--------------------------------------------------------------------------------
/Flym.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Flym
2 |
3 | Copyright (c) 2012-2015 Frederic Julian
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 |
18 |
19 | Some parts of this software are based on "Sparse rss" under the MIT license (see
20 | below). Please refers to the original project to identify which parts are under the
21 | MIT license.
22 |
23 | Copyright (c) 2010-2012 Stefan Handschuh
24 |
25 | Permission is hereby granted, free of charge, to any person obtaining a copy
26 | of this software and associated documentation files (the "Software"), to deal
27 | in the Software without restriction, including without limitation the rights
28 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29 | copies of the Software, and to permit persons to whom the Software is
30 | furnished to do so, subject to the following conditions:
31 |
32 | The above copyright notice and this permission notice shall be included in
33 | all copies or substantial portions of the Software.
34 |
35 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
41 | THE SOFTWARE.
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Flym DecSync
2 | ============
3 |
4 | [
](https://f-droid.org/app/org.decsync.flym)
7 |
8 | Flym DecSync is a fork of [Flym](https://github.com/FredJul/Flym) which adds synchronization using [DecSync](https://github.com/39aldo39/DecSync). To start synchronizing, all you have to do is synchronize your selected DecSync directory, using for example [Syncthing](https://syncthing.net).
9 |
10 | Donations
11 | ---------
12 |
13 | ### PayPal
14 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4V96AFD3S4TPJ)
15 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 | apply plugin: 'kotlin-kapt'
5 |
6 | androidExtensions {
7 | experimental = true
8 | }
9 |
10 | android {
11 | compileSdkVersion 31
12 | defaultConfig {
13 | applicationId "org.decsync.flym"
14 | minSdkVersion 21
15 | targetSdkVersion 31
16 | versionCode 46
17 | versionName "2.7.2"
18 | }
19 |
20 | compileOptions {
21 | sourceCompatibility JavaVersion.VERSION_1_8
22 | targetCompatibility JavaVersion.VERSION_1_8
23 |
24 | kotlinOptions {
25 | jvmTarget = "1.8"
26 | }
27 | }
28 |
29 | lintOptions {
30 | // if true, stop the gradle build if errors are found
31 | abortOnError true
32 | }
33 |
34 | File localProps = project.rootProject.file('local.properties')
35 | Properties properties = new Properties()
36 | if (localProps.exists()) {
37 | properties.load(localProps.newDataInputStream())
38 | }
39 |
40 | signingConfigs {
41 | debug {
42 | if (properties.getProperty("KEYSTORE_PATH") != null) {
43 | storeFile file(properties.getProperty("KEYSTORE_PATH"))
44 | storePassword properties.getProperty("KEYSTORE_PASSWORD")
45 | keyAlias properties.getProperty("KEY_ALIAS")
46 | keyPassword properties.getProperty("KEY_PASSWORD")
47 | }
48 | }
49 | release {
50 | if (properties.getProperty("KEYSTORE_PATH") != null) {
51 | storeFile file(properties.getProperty("KEYSTORE_PATH"))
52 | storePassword properties.getProperty("KEYSTORE_PASSWORD")
53 | keyAlias properties.getProperty("KEY_ALIAS")
54 | keyPassword properties.getProperty("KEY_PASSWORD")
55 | }
56 | }
57 | }
58 |
59 | buildTypes {
60 | release {
61 | minifyEnabled true
62 | shrinkResources true
63 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
64 | if (properties.getProperty("KEYSTORE_PATH") != null) {
65 | signingConfig signingConfigs.release
66 | }
67 | }
68 | }
69 |
70 | sourceSets {
71 | main.java.srcDirs += 'src/main/kotlin'
72 | }
73 | }
74 |
75 | kapt {
76 | arguments {
77 | arg("room.schemaLocation", "$projectDir/schemas")
78 | }
79 | }
80 |
81 | dependencies {
82 | implementation fileTree(dir: 'libs', include: ['*.jar'])
83 |
84 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
85 | implementation 'androidx.legacy:legacy-support-v4:1.0.0'
86 |
87 | def lifecycle_version = "2.2.0"
88 | implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
89 |
90 | def room_version = "2.4.0"
91 | implementation "androidx.room:room-runtime:$room_version"
92 | kapt "androidx.room:room-compiler:$room_version"
93 |
94 | implementation 'androidx.appcompat:appcompat:1.4.0'
95 | implementation 'com.google.android.material:material:1.4.0'
96 | implementation 'androidx.cardview:cardview:1.0.0'
97 | implementation 'androidx.recyclerview:recyclerview:1.2.1'
98 | def anko_version = '0.10.8'
99 | implementation "org.jetbrains.anko:anko-sdk21:$anko_version"
100 | implementation "org.jetbrains.anko:anko-sdk21-listeners:$anko_version"
101 | implementation "org.jetbrains.anko:anko-appcompat-v7:$anko_version"
102 | implementation "org.jetbrains.anko:anko-design:$anko_version"
103 |
104 | def okhttp_version = '4.9.0'
105 | implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
106 | implementation "com.squareup.okhttp3:okhttp-urlconnection:$okhttp_version"
107 |
108 | def glide_version = '4.11.0'
109 | implementation "com.github.bumptech.glide:glide:$glide_version"
110 | kapt "com.github.bumptech.glide:compiler:$glide_version"
111 |
112 | implementation 'androidx.core:core-ktx:1.7.0'
113 | implementation 'androidx.paging:paging-runtime-ktx:3.1.0'
114 | implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
115 | implementation 'androidx.preference:preference-ktx:1.1.1'
116 | implementation 'org.jsoup:jsoup:1.13.1'
117 | implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
118 | implementation 'com.github.Tunous:SwipeActionView:1.3.1'
119 | implementation 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1'
120 | implementation 'com.github.jrvansuita:MaterialAbout:0.2.3'
121 | implementation 'q.rorbin:badgeview:1.1.3'
122 | implementation 'net.dankito.readability4j:readability4j:1.0.5'
123 | implementation 'pub.devrel:easypermissions:3.0.0'
124 | implementation 'com.rometools:rome-opml:1.15.0'
125 | implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1'
126 | implementation 'org.decsync:libdecsync:2.2.1'
127 | implementation 'com.nononsenseapps:filepicker:4.2.1'
128 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'
129 | implementation 'com.github.AppIntro:AppIntro:6.1.0'
130 |
131 | testImplementation 'junit:junit:4.13.2'
132 | }
133 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/fred/Android/Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 |
11 | # for OOS, no need to remove all info
12 | -renamesourcefileattribute SourceFile
13 | -keepattributes SourceFile,LineNumberTable
14 | -keepnames class *
15 | -keepclasseswithmembernames class * { *; }
16 |
17 | # for the search
18 | -keep class android.support.v7.widget.SearchView { *; }
19 |
20 | # for anko
21 | -dontwarn org.jetbrains.anko.internals.AnkoInternals
22 |
23 | # for glide
24 | -keep public class * implements com.bumptech.glide.module.GlideModule
25 | -keep public class * extends com.bumptech.glide.AppGlideModule
26 | -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
27 | **[] $VALUES;
28 | public *;
29 | }
30 |
31 | # OkHttp
32 | -keepattributes Signature
33 | -keepattributes *Annotation*
34 | -keep class okhttp3.** { *; }
35 | -keep interface okhttp3.** { *; }
36 | -dontwarn okhttp3.**
37 | -dontwarn okio.**
38 |
39 | # Rome lib
40 | -keep class com.rometools.** { *; }
41 | -dontwarn java.beans.**
42 | -dontwarn javax.**
43 | -dontwarn org.jaxen.**
44 | -dontwarn org.slf4j.**
45 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/39aldo39/Flym-DecSync/87194f32c675c5c395030feaa93aa12ef88f7b90/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/MyAppGlideModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym
19 |
20 | import android.content.Context
21 | import com.bumptech.glide.GlideBuilder
22 | import com.bumptech.glide.annotation.GlideModule
23 | import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory
24 | import com.bumptech.glide.module.AppGlideModule
25 |
26 | @GlideModule
27 | class MyAppGlideModule : AppGlideModule() {
28 | override fun applyOptions(context: Context, builder: GlideBuilder) {
29 | val diskCacheSizeBytes = 1024 * 1024 * 50 // 50 MB
30 | builder.setDiskCache(InternalCacheDiskCacheFactory(context, diskCacheSizeBytes.toLong()))
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/converters/Converters.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.data.converters
19 |
20 | import androidx.room.TypeConverter
21 | import java.util.Date
22 |
23 | class Converters {
24 | @TypeConverter
25 | fun fromTimestamp(value: Long?): Date? {
26 | return if (value == null) null else Date(value)
27 | }
28 |
29 | @TypeConverter
30 | fun dateToTimestamp(date: Date?): Long? {
31 | return date?.time
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/dao/FeedDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.data.dao
19 |
20 | import androidx.lifecycle.LiveData
21 | import androidx.room.Dao
22 | import androidx.room.Delete
23 | import androidx.room.Insert
24 | import androidx.room.OnConflictStrategy
25 | import androidx.room.Query
26 | import androidx.room.Update
27 | import org.decsync.flym.data.entities.DecsyncCategory
28 | import org.decsync.flym.data.entities.DecsyncFeed
29 | import org.decsync.flym.data.entities.Feed
30 | import org.decsync.flym.data.entities.FeedWithCount
31 |
32 | private const val DECSYNC_FEED_SELECT = "feedLink, feedTitle, groupId"
33 | private const val DECSYNC_FEED_WHERE = "isGroup = 0 AND feedLink != ''"
34 | private const val DECSYNC_CATEGORY_SELECT = "feedLink, feedTitle"
35 | private const val DECSYNC_CATEGORY_WHERE = "isGroup = 1 AND feedLink != '' AND feedTitle NOT NULL"
36 | private const val ENTRY_COUNT = "(SELECT COUNT(*) FROM entries WHERE feedId IS f.feedId AND read = 0)"
37 |
38 | @Dao
39 | abstract class FeedDao {
40 |
41 | @ExperimentalStdlibApi
42 | @get:Query("SELECT $DECSYNC_FEED_SELECT FROM feeds WHERE $DECSYNC_FEED_WHERE")
43 | abstract val observeAllDecsyncFeeds: LiveData>
44 |
45 | @ExperimentalStdlibApi
46 | @get:Query("SELECT $DECSYNC_CATEGORY_SELECT FROM feeds WHERE $DECSYNC_CATEGORY_WHERE")
47 | abstract val observeAllDecsyncCategories: LiveData>
48 |
49 | @get:Query("SELECT * FROM feeds WHERE isGroup = 0")
50 | abstract val allNonGroupFeeds: List
51 |
52 | @Query("SELECT * FROM feeds WHERE isGroup = 0 and groupId = :groupId")
53 | abstract fun allFeedsInGroup(groupId: Long): List
54 |
55 | @get:Query("SELECT * FROM feeds ORDER BY groupId DESC, displayPriority ASC, feedId ASC")
56 | abstract val all: List
57 |
58 | @get:Query("SELECT * FROM feeds ORDER BY groupId DESC, displayPriority ASC, feedId ASC")
59 | abstract val observeAll: LiveData>
60 |
61 | @get:Query("SELECT *, $ENTRY_COUNT AS entryCount FROM feeds AS f ORDER BY groupId DESC, displayPriority ASC, feedId ASC")
62 | abstract val observeAllWithCount: LiveData>
63 |
64 | @Query("SELECT * FROM feeds WHERE feedId IS :id LIMIT 1")
65 | abstract fun findById(id: Long): Feed?
66 |
67 | @Query("SELECT * FROM feeds WHERE feedLink IS :link")
68 | abstract fun findByLink(link: String): Feed?
69 |
70 | @Query("DELETE FROM feeds WHERE feedLink IS :link")
71 | abstract fun deleteByLink(link: String)
72 |
73 | @Query("UPDATE feeds SET retrieveFullText = 1 WHERE feedId = :feedId")
74 | abstract fun enableFullTextRetrieval(feedId: Long)
75 |
76 | @Query("UPDATE feeds SET retrieveFullText = 0 WHERE feedId = :feedId")
77 | abstract fun disableFullTextRetrieval(feedId: Long)
78 |
79 | @Query("UPDATE feeds SET fetchError = 1 WHERE feedId = :feedId")
80 | abstract fun setFetchError(feedId: Long)
81 |
82 | @Insert(onConflict = OnConflictStrategy.REPLACE)
83 | abstract fun insert(vararg feeds: Feed): List
84 |
85 | @Update
86 | abstract fun update(vararg feeds: Feed)
87 |
88 | @Delete
89 | abstract fun delete(vararg feeds: Feed)
90 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/dao/TaskDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.data.dao
19 |
20 | import androidx.lifecycle.LiveData
21 | import androidx.room.Dao
22 | import androidx.room.Delete
23 | import androidx.room.Insert
24 | import androidx.room.OnConflictStrategy
25 | import androidx.room.Query
26 | import androidx.room.Transaction
27 | import androidx.room.Update
28 | import org.decsync.flym.data.entities.Task
29 |
30 |
31 | @Dao
32 | abstract class TaskDao {
33 | @get:Query("SELECT * FROM tasks")
34 | abstract val all: List
35 |
36 | @get:Query("SELECT * FROM tasks")
37 | abstract val observeAll: LiveData>
38 |
39 | @get:Query("SELECT * FROM tasks WHERE imageLinkToDl = ''")
40 | abstract val mobilizeTasks: List
41 |
42 | @Query("SELECT COUNT(*) FROM tasks WHERE imageLinkToDl = '' AND entryId = :itemId")
43 | abstract fun observeItemMobilizationTasksCount(itemId: String): LiveData
44 |
45 | @get:Query("SELECT * FROM tasks WHERE imageLinkToDl != ''")
46 | abstract val downloadTasks: List
47 |
48 | @Insert(onConflict = OnConflictStrategy.REPLACE)
49 | protected abstract fun insertInternal(task: Task)
50 |
51 | @Transaction
52 | open fun insert(vararg tasks: Task) {
53 | for (task in tasks) {
54 | try {
55 | insertInternal(task) // Needed to avoid failing on all insert if a single one is failing
56 | } catch (t: Throwable) {
57 | }
58 | }
59 | }
60 |
61 | @Update
62 | abstract fun update(vararg tasks: Task)
63 |
64 | @Delete
65 | abstract fun delete(vararg tasks: Task)
66 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/entities/DecsyncArticle.kt:
--------------------------------------------------------------------------------
1 | package org.decsync.flym.data.entities
2 |
3 | import org.decsync.library.items.Rss
4 | import java.util.*
5 |
6 | @ExperimentalStdlibApi
7 | data class DecsyncArticle(
8 | val uri: String,
9 | val read: Boolean,
10 | val favorite: Boolean,
11 | val publicationDate: Date
12 | ) {
13 | fun getRssArticle(): Rss.Article {
14 | val time = publicationDate.time
15 | val date = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
16 | date.timeInMillis = time
17 | val year = date.get(Calendar.YEAR)
18 | val month = date.get(Calendar.MONTH) + 1
19 | val day = date.get(Calendar.DAY_OF_MONTH)
20 | return Rss.Article(uri, read, favorite, year, month, day)
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/entities/DecsyncFeed.kt:
--------------------------------------------------------------------------------
1 | package org.decsync.flym.data.entities
2 |
3 | import org.decsync.flym.App
4 | import org.decsync.library.items.Rss
5 |
6 | @ExperimentalStdlibApi
7 | data class DecsyncFeed(
8 | val feedLink: String,
9 | val feedTitle: String?,
10 | val groupId: Long?
11 | ) {
12 | fun getRssFeed(): Rss.Feed {
13 | return Rss.Feed(feedLink, feedTitle, groupId) {
14 | groupId?.let { App.db.feedDao().findById(it)?.link }
15 | }
16 | }
17 | }
18 |
19 | @ExperimentalStdlibApi
20 | data class DecsyncCategory(
21 | val feedLink: String,
22 | val feedTitle: String
23 | ) {
24 | fun getRssCategory() : Rss.Category {
25 | return Rss.Category(feedLink, feedTitle, null) {
26 | // We do not support nested categories
27 | // Only changes are detected, so always giving the default value of null is fine
28 | null
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/entities/Entry.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.data.entities
19 |
20 | import android.content.Context
21 | import android.os.Parcelable
22 | import android.text.format.DateFormat
23 | import android.text.format.DateUtils
24 | import androidx.core.text.HtmlCompat
25 | import androidx.room.Entity
26 | import androidx.room.ForeignKey
27 | import androidx.room.Index
28 | import androidx.room.PrimaryKey
29 | import com.rometools.rome.feed.synd.SyndEntry
30 | import kotlinx.android.parcel.Parcelize
31 | import net.fred.feedex.R
32 | import org.decsync.flym.utils.sha1
33 | import java.util.*
34 |
35 | @Parcelize
36 | @Entity(tableName = "entries",
37 | indices = [(Index(value = ["feedId"])), (Index(value = ["link"], unique = true)), (Index(value = ["uri"], unique = true))],
38 | foreignKeys = [(ForeignKey(entity = Feed::class,
39 | parentColumns = ["feedId"],
40 | childColumns = ["feedId"],
41 | onDelete = ForeignKey.CASCADE))])
42 | data class Entry(@PrimaryKey
43 | var id: String = "",
44 | var feedId: Long = 0L,
45 | var link: String? = null,
46 | var uri: String? = null,
47 | var fetchDate: Date = Date(),
48 | var publicationDate: Date = fetchDate, // important to know if the publication date has been set
49 | var title: String? = null,
50 | var description: String? = null,
51 | var mobilizedContent: String? = null,
52 | var imageLink: String? = null,
53 | var author: String? = null,
54 | var read: Boolean = false,
55 | var favorite: Boolean = false) : Parcelable {
56 |
57 | fun getReadablePublicationDate(context: Context): String =
58 | if (DateUtils.isToday(publicationDate.time)) {
59 | DateFormat.getTimeFormat(context).format(publicationDate)
60 | } else {
61 | DateFormat.getMediumDateFormat(context).format(publicationDate) + ' ' +
62 | DateFormat.getTimeFormat(context).format(publicationDate)
63 | }
64 | }
65 |
66 | fun SyndEntry.toDbFormat(context: Context, feedId: Long): Entry {
67 | val item = Entry()
68 | item.id = (feedId.toString() + "_" + (link ?: uri ?: title
69 | ?: UUID.randomUUID().toString())).sha1()
70 | item.feedId = feedId
71 | if (title != null) {
72 | item.title = HtmlCompat.fromHtml(title, HtmlCompat.FROM_HTML_MODE_LEGACY).toString()
73 | } else {
74 | item.title = context.getString(R.string.entry_default_title)
75 | }
76 | item.description = contents.getOrNull(0)?.value ?: description?.value
77 | item.link = link
78 | item.uri = uri
79 |
80 | enclosures?.forEach { if (it.type.contains("image")) { item.imageLink = it.url } }
81 | if (item.imageLink == null) {
82 | foreignMarkup?.forEach {
83 | if (it.namespace?.prefix == "media" && it.name == "content") {
84 | it.attributes.forEach { mc ->
85 | if (mc.name == "url") item.imageLink = mc.value
86 | }
87 | }
88 | }
89 | }
90 |
91 | item.author = author
92 |
93 | val date = publishedDate ?: updatedDate
94 | item.publicationDate = if (date?.before(item.publicationDate) == true) date else item.publicationDate
95 |
96 | return item
97 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/entities/EntryWithFeed.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.data.entities
19 |
20 | import android.os.Parcelable
21 | import androidx.room.Embedded
22 | import kotlinx.android.parcel.Parcelize
23 |
24 |
25 | @Parcelize
26 | class EntryWithFeed(
27 | @Embedded
28 | var entry: Entry,
29 | var feedTitle: String? = null,
30 | var feedLink: String = "",
31 | var feedImageLink: String? = null,
32 | var groupId: String? = null) : Parcelable
33 |
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/entities/Feed.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.data.entities
19 |
20 | import android.os.Parcelable
21 | import androidx.room.ColumnInfo
22 | import androidx.room.Entity
23 | import androidx.room.ForeignKey
24 | import androidx.room.Index
25 | import androidx.room.PrimaryKey
26 | import com.amulyakhare.textdrawable.TextDrawable
27 | import com.amulyakhare.textdrawable.util.ColorGenerator
28 | import com.rometools.rome.feed.synd.SyndFeed
29 | import kotlinx.android.parcel.Parcelize
30 |
31 |
32 | val DELIMITERS = arrayOf(" ", "-", "&", ":", "|")
33 |
34 | @Parcelize
35 | @Entity(tableName = "feeds",
36 | indices = [(Index(value = ["groupId"])), (Index(value = ["feedId", "feedLink"], unique = true))],
37 | foreignKeys = [(ForeignKey(entity = Feed::class,
38 | parentColumns = ["feedId"],
39 | childColumns = ["groupId"],
40 | onDelete = ForeignKey.CASCADE))])
41 | data class Feed(
42 | @PrimaryKey(autoGenerate = true)
43 | @ColumnInfo(name = "feedId")
44 | var id: Long = 0L,
45 | @ColumnInfo(name = "feedLink")
46 | var link: String = "",
47 | @ColumnInfo(name = "feedTitle")
48 | var title: String? = null,
49 | @ColumnInfo(name = "feedImageLink")
50 | var imageLink: String? = null,
51 | var fetchError: Boolean = false,
52 | var retrieveFullText: Boolean = false,
53 | var isGroup: Boolean = false,
54 | var groupId: Long? = null,
55 | var displayPriority: Int = 0,
56 | @Deprecated("Not used anymore")
57 | var lastManualActionUid: String = "") : Parcelable {
58 |
59 | companion object {
60 |
61 | const val ALL_ENTRIES_ID = -1L
62 |
63 | fun getLetterDrawable(feedId: Long, feedTitle: String?, rounded: Boolean = false): TextDrawable {
64 | val feedName = feedTitle.orEmpty()
65 |
66 | val color = ColorGenerator.MATERIAL.getColor(feedId) // The color is specific to the feedId (which shouldn't change)
67 | val lettersForName = getLettersForName(feedName)
68 | return if (rounded) {
69 | TextDrawable.builder().buildRound(lettersForName, color)
70 | } else {
71 | TextDrawable.builder().buildRect(lettersForName, color)
72 | }
73 | }
74 |
75 | internal fun getLettersForName(feedName: String): String {
76 | val split = feedName.split(*DELIMITERS).filter { it != "" } // filtering empty strings that occur when multiple delimiters are matched, e. g. colon-whitespace: ": "
77 |
78 | val letters = when {
79 | split.size >= 2 -> String(charArrayOf(split[0][0], split[1][0])) // first letter of first and second word
80 | split.isEmpty() -> ""
81 | else -> split[0][0].toString()
82 | }
83 |
84 | return letters.toUpperCase()
85 | }
86 | }
87 |
88 | fun update(feed: SyndFeed) {
89 | if (title == null) {
90 | title = feed.title
91 | }
92 |
93 | if (feed.image?.url != null) {
94 | imageLink = feed.image?.url
95 | }
96 |
97 | // no error anymore since we just got a feedWithCount
98 | fetchError = false
99 | }
100 |
101 | fun getLetterDrawable(rounded: Boolean = false): TextDrawable {
102 | return getLetterDrawable(id, title, rounded)
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/entities/FeedWithCount.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.data.entities
19 |
20 | import android.os.Parcelable
21 | import androidx.room.Embedded
22 | import kotlinx.android.parcel.Parcelize
23 |
24 | @Parcelize
25 | data class FeedWithCount(
26 | @Embedded
27 | var feed: Feed,
28 | var entryCount: Int = 0) : Parcelable {
29 |
30 | fun getEntryCountString(): String {
31 | return if (entryCount > 0) entryCount.toString() else ""
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/entities/SearchFeedResult.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.data.entities
19 |
20 | import android.os.Parcelable
21 | import kotlinx.android.parcel.Parcelize
22 |
23 | @Parcelize
24 | data class SearchFeedResult(
25 | var iconUrl: String? = "",
26 | var link: String = "",
27 | var name: String = "",
28 | var desc: String = "",
29 | var isAdded: Boolean = false) : Parcelable
30 |
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/entities/Task.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.data.entities
19 |
20 | import android.os.Parcelable
21 | import androidx.room.Entity
22 | import androidx.room.ForeignKey
23 | import androidx.room.Index
24 | import kotlinx.android.parcel.Parcelize
25 |
26 | @Parcelize
27 | @Entity(tableName = "tasks",
28 | primaryKeys = ["entryId", "imageLinkToDl"],
29 | indices = [(Index(value = ["entryId"]))],
30 | foreignKeys = [(ForeignKey(entity = Entry::class,
31 | parentColumns = ["id"],
32 | childColumns = ["entryId"],
33 | onDelete = ForeignKey.CASCADE))])
34 | data class Task(
35 | var entryId: String = "",
36 | var imageLinkToDl: String = "",
37 | var numberAttempt: Int = 0) : Parcelable
38 |
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/data/utils/PrefConstants.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.data.utils
19 |
20 |
21 | object PrefConstants {
22 |
23 | const val FIRST_OPEN = "first_open"
24 |
25 | const val IS_REFRESHING = "is_refreshing"
26 |
27 | const val REFRESH_ENABLED = "refresh_enabled"
28 | const val REFRESH_NOTIFICATION_ENABLED = "enable_refresh_notification"
29 | const val REFRESH_INTERVAL = "refresh_interval"
30 | const val REFRESH_ON_STARTUP = "refresh_on_startup"
31 | const val REFRESH_WIFI_ONLY = "refresh_wifi_only"
32 |
33 | const val THEME = "theme"
34 | const val DISPLAY_THUMBNAILS = "display_thumbnails"
35 | const val DISPLAY_IMAGES = "display_images"
36 |
37 | const val PRELOAD_IMAGE_MODE = "preload_image_mode"
38 | const val PRELOAD_IMAGE_MODE__WIFI_ONLY = "WIFI_ONLY_PRELOAD"
39 | const val PRELOAD_IMAGE_MODE__ALWAYS = "ALWAYS_PRELOAD"
40 |
41 | const val REMOVE_DUPLICATES = "remove_duplicates"
42 |
43 | const val FILTER_KEYWORDS = "filter_keywords"
44 |
45 | const val KEEP_TIME = "keep_time"
46 | const val KEEP_TIME_UNREAD = "keep_time_unread"
47 |
48 | const val FONT_SIZE = "font_size"
49 |
50 | const val OPEN_BROWSER_DIRECTLY = "open_browser_directly"
51 | const val HIDE_BUTTON_MARK_ALL_AS_READ = "hide_button_mark_all_as_read"
52 | const val HIDE_NAVIGATION_ON_SCROLL = "hide_navigation_on_scroll"
53 | const val SORT_ORDER = "sort_order"
54 |
55 | const val ENABLE_SWIPE_ENTRY = "enable_swipe_entry"
56 |
57 | const val DECSYNC_ENABLED = "decsync.enabled"
58 | const val DECSYNC_USE_SAF = "decsync.use_saf"
59 | const val UPDATE_FORCES_SAF = "update_forces_saf"
60 | const val DECSYNC_FILE = "decsync.directory"
61 | const val DECSYNC_MANAGE_DATA = "decsync.manage_data"
62 |
63 | const val INTRO_DONE = "intro_done"
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/service/AutoRefreshJobService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.service
19 |
20 | import android.app.job.JobInfo
21 | import android.app.job.JobParameters
22 | import android.app.job.JobScheduler
23 | import android.app.job.JobService
24 | import android.content.ComponentName
25 | import android.content.Context
26 | import android.os.Build
27 | import kotlinx.coroutines.ObsoleteCoroutinesApi
28 | import org.decsync.flym.data.utils.PrefConstants
29 | import org.decsync.flym.utils.getPrefBoolean
30 | import org.decsync.flym.utils.getPrefString
31 | import org.jetbrains.anko.doAsync
32 | import kotlin.math.max
33 |
34 | @ExperimentalStdlibApi
35 | @ObsoleteCoroutinesApi
36 | class AutoRefreshJobService : JobService() {
37 |
38 | companion object {
39 | var ignoreNextJob = false
40 |
41 | private const val TWO_HOURS = "7200"
42 | private const val JOB_ID = 0
43 |
44 | fun initAutoRefresh(context: Context) {
45 |
46 | // DO NOT USE ANKO TO RETRIEVE THE SERVICE HERE (crash on API 21)
47 | val jobSchedulerService = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
48 |
49 | val time = max(300, context.getPrefString(PrefConstants.REFRESH_INTERVAL, TWO_HOURS)!!.toInt())
50 |
51 | if (context.getPrefBoolean(PrefConstants.REFRESH_ENABLED, true)) {
52 | val builder = JobInfo.Builder(JOB_ID, ComponentName(context, AutoRefreshJobService::class.java))
53 | .setPeriodic(time * 1000L)
54 | .setPersisted(true)
55 | .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
56 |
57 | if (Build.VERSION.SDK_INT >= 26) {
58 | builder.setRequiresBatteryNotLow(true)
59 | .setRequiresStorageNotLow(true)
60 | }
61 |
62 | ignoreNextJob = true // We can't add a initial delay with JobScheduler, so let's do this little hack instead
63 | jobSchedulerService.schedule(builder.build())
64 | } else {
65 | jobSchedulerService.cancel(JOB_ID)
66 | }
67 | }
68 | }
69 |
70 | override fun onStartJob(params: JobParameters): Boolean {
71 | if (!ignoreNextJob && !getPrefBoolean(PrefConstants.IS_REFRESHING, false)) {
72 | doAsync {
73 | FetcherService.fetch(this@AutoRefreshJobService, true, FetcherService.ACTION_REFRESH_FEEDS)
74 | jobFinished(params, false)
75 | }
76 | return true
77 | }
78 |
79 | ignoreNextJob = false
80 |
81 | return false
82 | }
83 |
84 | override fun onStopJob(params: JobParameters): Boolean {
85 | return false
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/ui/about/AboutActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.ui.about
19 |
20 | import android.os.Bundle
21 | import android.view.MenuItem
22 | import androidx.appcompat.app.AppCompatActivity
23 | import com.vansuita.materialabout.builder.AboutBuilder
24 | import net.fred.feedex.R
25 | import org.decsync.flym.utils.setupTheme
26 |
27 |
28 | class AboutActivity : AppCompatActivity() {
29 |
30 | override fun onCreate(savedInstanceState: Bundle?) {
31 | setupTheme()
32 |
33 | super.onCreate(savedInstanceState)
34 |
35 | supportActionBar?.setDisplayHomeAsUpEnabled(true)
36 |
37 | val view = AboutBuilder.with(this)
38 | .setPhoto(R.mipmap.profile_picture)
39 | .setCover(R.mipmap.profile_cover)
40 | .setName("Aldo Gunsing")
41 | .setSubTitle(R.string.about_screen_based_on_flym)
42 | .setBrief(R.string.about_screen_info)
43 | .setAppIcon(R.drawable.ic_launcher_foreground)
44 | .setAppName(R.string.app_name)
45 | .addGitHubLink("39aldo39/Flym-DecSync")
46 | .addShareAction(R.string.app_name)
47 | .setWrapScrollView(true)
48 | .setLinksAnimated(true)
49 | .setShowAsCard(true)
50 | .build()
51 |
52 | setContentView(view)
53 | }
54 |
55 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
56 | when (item.itemId) {
57 | android.R.id.home -> onBackPressed()
58 | }
59 |
60 | return true
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/ui/discover/DiscoverFragment.kt:
--------------------------------------------------------------------------------
1 | package org.decsync.flym.ui.discover
2 |
3 | import android.content.Context
4 | import android.os.Bundle
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import android.widget.*
9 | import androidx.fragment.app.Fragment
10 | import net.fred.feedex.R
11 | import org.decsync.flym.GlideApp
12 | import org.decsync.flym.data.entities.Feed
13 | import org.jetbrains.anko.layoutInflater
14 |
15 |
16 | class DiscoverFragment : Fragment(), AdapterView.OnItemClickListener {
17 |
18 | companion object {
19 | const val TAG = "DiscoverFragment"
20 |
21 | @JvmStatic
22 | fun newInstance() = DiscoverFragment()
23 | }
24 |
25 | private lateinit var manageFeeds: FeedManagementInterface
26 |
27 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
28 | val view = inflater.inflate(R.layout.fragment_discover, container, false)
29 | initGridView(view)
30 | return view
31 | }
32 |
33 | override fun onAttach(context: Context) {
34 | super.onAttach(context)
35 | manageFeeds = context as FeedManagementInterface
36 | }
37 |
38 | private fun initGridView(view: View) {
39 | val gvTopics: GridView = view.findViewById(R.id.gv_topics)
40 | val topics = view.context.resources.getStringArray(R.array.discover_topics)
41 | gvTopics.adapter = TopicAdapter(view.context, topics)
42 | gvTopics.onItemClickListener = this
43 | }
44 |
45 | override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
46 | val topic = parent?.getItemAtPosition(position) as String
47 | manageFeeds.searchForFeed("#$topic")
48 | }
49 |
50 | class TopicAdapter(context: Context, topics: Array) :
51 | ArrayAdapter(context, R.layout.item_discover_topic, topics) {
52 |
53 | private class ItemViewHolder {
54 | var image: ImageView? = null
55 | var title: TextView? = null
56 | }
57 |
58 | private fun setTopicTitle(viewHolder: ItemViewHolder, topic: String) {
59 | viewHolder.title?.text = topic
60 | }
61 |
62 | private fun setTopicImage(viewHolder: ItemViewHolder, topic: String) {
63 | val letterDrawable = Feed.getLetterDrawable(topic.hashCode().toLong(), topic)
64 | viewHolder.image?.let { iv ->
65 | GlideApp.with(context).clear(iv)
66 | iv.setImageDrawable(letterDrawable)
67 | }
68 | }
69 |
70 | override fun getView(i: Int, view: View?, viewGroup: ViewGroup): View {
71 | val viewHolder: ItemViewHolder
72 | var inflatedView: View? = view
73 | if (inflatedView == null) {
74 | inflatedView = context.layoutInflater.inflate(R.layout.item_discover_topic, null)
75 | viewHolder = ItemViewHolder()
76 | inflatedView?.let { vw ->
77 | viewHolder.image = vw.findViewById(R.id.iv_topic_image) as ImageView
78 | viewHolder.title = vw.findViewById(R.id.tv_topic_title) as TextView
79 | }
80 | } else {
81 | viewHolder = inflatedView.tag as ItemViewHolder
82 | }
83 | val item = getItem(i)
84 | item?.let { it ->
85 | setTopicImage(viewHolder, it)
86 | setTopicTitle(viewHolder, it)
87 | }
88 | inflatedView?.tag = viewHolder
89 | return inflatedView!!
90 | }
91 | }
92 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/ui/discover/FeedManagementInterface.kt:
--------------------------------------------------------------------------------
1 | package org.decsync.flym.ui.discover
2 |
3 | import android.view.View
4 | import org.decsync.flym.data.entities.SearchFeedResult
5 |
6 | interface FeedManagementInterface {
7 |
8 | fun searchForFeed(query: String)
9 |
10 | fun addFeed(view: View, title: String, link: String)
11 |
12 | fun deleteFeed(view: View, feed: SearchFeedResult)
13 |
14 | fun previewFeed(view: View, feed: SearchFeedResult)
15 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/ui/discover/SquareGridItemLayout.kt:
--------------------------------------------------------------------------------
1 | package org.decsync.flym.ui.discover
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import androidx.constraintlayout.widget.ConstraintLayout
6 |
7 | class SquareGridItemLayout : ConstraintLayout {
8 | constructor(context: Context) : super(context)
9 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
10 | constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)
11 |
12 | override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
13 | super.onMeasure(widthMeasureSpec, widthMeasureSpec)
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/ui/entrydetails/EntryDetailsActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.ui.entrydetails
19 |
20 | import android.os.Bundle
21 | import android.util.TypedValue
22 | import android.view.MenuItem
23 | import androidx.appcompat.app.AppCompatActivity
24 | import kotlinx.coroutines.ObsoleteCoroutinesApi
25 | import net.fred.feedex.R
26 | import org.decsync.flym.utils.setupNoActionBarTheme
27 | import org.jetbrains.anko.backgroundColor
28 |
29 | @ExperimentalStdlibApi
30 | @ObsoleteCoroutinesApi
31 | class EntryDetailsActivity : AppCompatActivity() {
32 |
33 | override fun onCreate(savedInstanceState: Bundle?) {
34 | setupNoActionBarTheme()
35 |
36 | super.onCreate(savedInstanceState)
37 |
38 | val tv = TypedValue()
39 | if (theme.resolveAttribute(R.attr.colorPrimary, tv, true)) {
40 | window.decorView.backgroundColor = tv.data
41 | }
42 |
43 | if (savedInstanceState == null) {
44 | val fragment = EntryDetailsFragment().apply {
45 | arguments = intent.extras
46 | }
47 |
48 | supportFragmentManager
49 | .beginTransaction()
50 | .replace(android.R.id.content, fragment)
51 | .commitAllowingStateLoss()
52 | }
53 | }
54 |
55 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
56 | when (item.itemId) {
57 | android.R.id.home -> onBackPressed()
58 | }
59 |
60 | return false
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/ui/feeds/DrawerFeedAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.ui.feeds
19 |
20 | import android.os.Bundle
21 | import android.view.View
22 | import org.decsync.flym.data.entities.Feed
23 | import org.decsync.flym.data.entities.FeedWithCount
24 | import org.jetbrains.anko.sdk21.listeners.onClick
25 |
26 |
27 | private const val STATE_SELECTED_ID = "STATE_SELECTED_ID"
28 |
29 | open class FeedAdapter(groups: List) : BaseFeedAdapter(groups) {
30 |
31 | var selectedItemId = Feed.ALL_ENTRIES_ID
32 | set(newValue) {
33 | notifyParentDataSetChanged(true)
34 | field = newValue
35 | }
36 |
37 | override fun bindItem(itemView: View, feedWithCount: FeedWithCount) {
38 | itemView.isSelected = selectedItemId == feedWithCount.feed.id
39 |
40 | itemView.onClick {
41 | selectedItemId = feedWithCount.feed.id
42 | feedClickListener?.invoke(itemView, feedWithCount)
43 | }
44 | }
45 |
46 | override fun bindItem(itemView: View, group: FeedGroup) {
47 | itemView.isSelected = selectedItemId == group.feedWithCount.feed.id
48 |
49 | itemView.onClick {
50 | selectedItemId = group.feedWithCount.feed.id
51 | feedClickListener?.invoke(itemView, group.feedWithCount)
52 | }
53 | }
54 |
55 | override fun onSaveInstanceState(savedInstanceState: Bundle) {
56 | savedInstanceState.putLong(STATE_SELECTED_ID, selectedItemId)
57 | }
58 |
59 | override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
60 | selectedItemId = savedInstanceState?.getLong(STATE_SELECTED_ID) ?: Feed.ALL_ENTRIES_ID
61 | }
62 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/ui/feeds/EditFeedAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.ui.feeds
19 |
20 | import net.fred.feedex.R
21 |
22 | class EditFeedAdapter(groups: List) : BaseFeedAdapter(groups) {
23 | override val layoutId = R.layout.view_feed_edit
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/ui/feeds/FeedGroup.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.ui.feeds
19 |
20 | import com.bignerdranch.expandablerecyclerview.model.Parent
21 | import org.decsync.flym.data.entities.FeedWithCount
22 |
23 |
24 | class FeedGroup(val feedWithCount: FeedWithCount, val subFeeds: List) : Parent {
25 |
26 | override fun getChildList(): List {
27 | return subFeeds
28 | }
29 |
30 | override fun isInitiallyExpanded(): Boolean {
31 | return false
32 | }
33 |
34 | // needed to preserve expansion state
35 | override fun equals(other: Any?): Boolean {
36 | if (this === other) return true
37 | if (javaClass != other?.javaClass) return false
38 |
39 | other as FeedGroup
40 |
41 | if (feedWithCount.feed.id != other.feedWithCount.feed.id) return false
42 |
43 | return true
44 | }
45 |
46 | override fun hashCode(): Int {
47 | return feedWithCount.feed.id.hashCode()
48 | }
49 |
50 | fun getEntryCountString(): String {
51 | val entryCount = if (subFeeds.isNotEmpty()) subFeeds.sumBy { it.entryCount } else feedWithCount.entryCount
52 | return if (entryCount > 0) entryCount.toString() else ""
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/ui/feeds/FeedListEditActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012-2018 Frederic Julian
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see //www.gnu.org/licenses/>.
16 | */
17 |
18 | package org.decsync.flym.ui.feeds
19 |
20 | import android.os.Bundle
21 | import android.view.MenuItem
22 | import androidx.appcompat.app.AppCompatActivity
23 | import net.fred.feedex.R
24 | import org.decsync.flym.utils.setupTheme
25 |
26 | class FeedListEditActivity : AppCompatActivity() {
27 |
28 | override fun onCreate(savedInstanceState: Bundle?) {
29 | setupTheme()
30 |
31 | super.onCreate(savedInstanceState)
32 |
33 | supportActionBar?.setDisplayHomeAsUpEnabled(true)
34 |
35 | setContentView(R.layout.activity_feed_list_edit)
36 | }
37 |
38 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
39 | when (item.itemId) {
40 | android.R.id.home -> onBackPressed()
41 | }
42 |
43 | return false
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/org/decsync/flym/ui/intro/SafUpdateActivity.kt:
--------------------------------------------------------------------------------
1 | package org.decsync.flym.ui.intro
2 |
3 | import android.content.Intent
4 | import android.os.Bundle
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import android.widget.Button
9 | import android.widget.CheckBox
10 | import android.widget.Toast
11 | import androidx.fragment.app.Fragment
12 | import com.github.appintro.AppIntro2
13 | import com.github.appintro.SlidePolicy
14 | import kotlinx.android.synthetic.main.activity_saf_update.*
15 | import net.fred.feedex.R
16 | import org.decsync.flym.data.utils.PrefConstants
17 | import org.decsync.flym.ui.main.MainActivity
18 | import org.decsync.flym.utils.putPrefBoolean
19 | import org.decsync.library.DecsyncPrefUtils
20 |
21 | @ExperimentalStdlibApi
22 | class SafUpdateActivity : AppIntro2() {
23 | private val slideSafDirectory = SlideSafDirectory()
24 |
25 | override fun onCreate(savedInstanceState: Bundle?) {
26 | super.onCreate(savedInstanceState)
27 |
28 | isSkipButtonEnabled = false
29 | isIndicatorEnabled = false
30 | showStatusBar(true)
31 |
32 | addSlide(slideSafDirectory)
33 | }
34 |
35 | override fun onIntroFinished() {
36 | super.onIntroFinished()
37 |
38 | putPrefBoolean(PrefConstants.UPDATE_FORCES_SAF, false)
39 |
40 | val decsyncEnabled = slideSafDirectory.decsyncEnabled
41 | putPrefBoolean(PrefConstants.DECSYNC_ENABLED, decsyncEnabled)
42 |
43 | val intent = Intent(this, MainActivity::class.java)
44 | startActivity(intent)
45 | finish()
46 | }
47 | }
48 |
49 | @ExperimentalStdlibApi
50 | class SlideSafDirectory : Fragment(), SlidePolicy {
51 | var decsyncEnabled = true
52 |
53 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
54 | val view = inflater.inflate(R.layout.activity_saf_update, container, false)
55 |
56 | val button = view.findViewById