first commit

This commit is contained in:
Thomas 2022-04-27 15:20:42 +02:00
commit 0f855c5ac2
710 changed files with 112474 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
*.iml
.gradle
/local.properties
/.idea/*
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

1
app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

122
app/build.gradle Normal file
View File

@ -0,0 +1,122 @@
plugins {
id 'com.android.application'
}
def flavor
android {
compileSdk 31
defaultConfig {
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
flavorDimensions "default"
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
productFlavors {
fdroid {
applicationId "fr.gouv.etalab.mastodon"
buildConfigField "boolean", "DONATIONS", "true"
buildConfigField "boolean", "push", "false"
flavor = "fdroid"
}
playstore {
applicationId "app.fedilab.android"
buildConfigField "boolean", "DONATIONS", "false"
buildConfigField "boolean", "push", "true"
flavor = "playstore"
}
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
buildFeatures {
viewBinding true
}
sourceSets {
playstore {
manifest.srcFile "src/playstore/AndroidManifest.xml"
java.srcDirs = ['src/main/java', 'src/playstore/java']
res.srcDirs = ['src/main/res', 'src/playstore/res']
}
fdroid {
java.srcDirs = ['src/main/java', 'src/fdroid/java']
res.srcDirs = ['src/main/res', 'src/fdroid/res']
}
}
configurations {
all {
exclude group: 'androidx.lifecycle', module: 'lifecycle-viewmodel-ktx'
}
}
}
allprojects {
repositories {
mavenLocal()
maven { url "https://jitpack.io" }
}
}
dependencies {
implementation project(':autoimageslider')
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation "com.google.code.gson:gson:2.8.6"
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.preference:preference:1.2.0'
implementation 'com.github.evozi:Cyanea:1.0.7'
implementation 'com.vanniktech:emoji-one:0.6.0'
implementation 'com.github.GrenderG:Toasty:1.5.2'
implementation 'org.framagit.tom79:SparkButton:1.0.13'
implementation "com.github.bumptech.glide:glide:4.12.0"
implementation 'com.github.mergehez:ArgPlayer:v3.1'
implementation ("com.github.bumptech.glide:recyclerview-integration:4.12.0") {
// Excludes the support library because it's already included by Glide.
transitive = false
}
implementation project(path: ':mytransl')
implementation project(path: ':ratethisapp')
annotationProcessor "com.github.bumptech.glide:compiler:4.12.0"
implementation 'jp.wasabeef:glide-transformations:4.3.0'
implementation 'com.github.penfeizhou.android.animation:apng:2.17.0'
implementation 'com.github.penfeizhou.android.animation:gif:2.17.0'
implementation 'com.google.android.exoplayer:exoplayer:2.16.1'
implementation 'com.github.piasy:rxandroidaudio:1.7.0'
implementation 'com.github.piasy:AudioProcessor:1.7.0'
implementation "androidx.work:work-runtime:2.7.1"
implementation 'app.futured.hauler:hauler:5.0.0'
implementation "com.github.chrisbanes:PhotoView:2.3.0"
implementation "ch.acra:acra-mail:5.5.0"
implementation "ch.acra:acra-limiter:5.5.0"
implementation "ch.acra:acra-notification:5.5.0"
implementation "com.madgag.spongycastle:bctls-jdk15on:1.58.0.0"
implementation 'com.github.UnifiedPush:android-connector:2.0.0'
// implementation 'com.github.UnifiedPush:android-foss_embedded_fcm_distributor:1.0.0-beta1'
playstoreImplementation 'com.github.UnifiedPush:android-embedded_fcm_distributor:1.1.0'
implementation 'com.burhanrashid52:photoeditor:1.5.1'
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
implementation 'androidx.lifecycle:lifecycle-livedata:2.4.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.4.1'
implementation 'androidx.navigation:navigation-fragment:2.4.1'
implementation 'androidx.navigation:navigation-ui:2.4.1'
testImplementation 'junit:junit:'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1'
}

21
app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,26 @@
package app.fedilab.android;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("app.fedilab.android", appContext.getPackageName());
}
}

View File

@ -0,0 +1,27 @@
/* Copyright 2022 Thomas Schneider
*
* This file is a part of Fedilab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
package app.fedilab.android.activities;
import app.fedilab.android.BaseMainActivity;
public class MainActivity extends BaseMainActivity {
@Override
protected void rateThisApp() {
// do nothing
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="my_images"
path="Android/data/fr.gouv.etalab.mastodon/files/Pictures" />
<cache-path
name="*"
path="." />
</paths>

View File

@ -0,0 +1,187 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="app.fedilab.android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name=".MainApplication"
tools:replace="android:allowBackup"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
>
<activity
android:name=".activities.MainActivity"
android:exported="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:exported="true"
android:name=".activities.LoginActivity"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="backtofedilab"
android:scheme="fedilab" />
</intent-filter>
</activity>
<activity
android:name=".activities.WebviewConnectActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".activities.ContextActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".activities.DraftActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".activities.ComposeActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="stateVisible"
android:label="@string/compose" />
<activity
android:name=".activities.StatusInfoActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".activities.WebviewActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".activities.ProfileActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/account" />
<activity
android:name=".activities.ScheduledActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/scheduled" />
<service
android:name=".services.PostMessageService"
android:label="@string/post_message" />
<activity
android:name=".activities.SearchResultTabActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@style/AppThemeBar"
android:label="@string/search" />
<activity
android:name=".activities.ReorderTimelinesActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/reorder_timelines"
android:theme="@style/AppThemeBar" />
<activity
android:name=".activities.ActionActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/interactions"
android:theme="@style/AppThemeBar" />
<activity
android:name=".activities.MastodonListActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/action_lists"
android:theme="@style/AppThemeBar" />
<activity
android:name=".activities.SettingsActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/settings"
android:theme="@style/AppThemeBar" />
<activity
android:name=".activities.InstanceActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/action_about_instance"
android:theme="@style/DialogDark" />
<activity
android:name=".activities.InstanceProfileActivity"
android:excludeFromRecents="true"
android:theme="@style/DialogDark" />
<activity
android:name=".activities.ProxyActivity"
android:excludeFromRecents="true"
android:theme="@style/DialogDark" />
<activity
android:name=".activities.HashTagActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".activities.MediaActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@style/TransparentDark" />
<activity
android:name=".activities.InstanceHealthActivity"
android:excludeFromRecents="true"
android:theme="@style/DialogDark" />
<activity
android:name=".activities.ReportActivity"
android:theme="@style/AppThemeBarDark"
android:windowSoftInputMode="stateVisible" />
<activity
android:name=".activities.CustomSharingActivity"
android:label="@string/settings_title_custom_sharing"
android:windowSoftInputMode="stateVisible"
android:theme="@style/AppThemeBarDark" />
<activity
android:name=".activities.FilterActivity"
android:label="@string/filters"
android:theme="@style/AppThemeBarDark"
android:windowSoftInputMode="stateVisible" />
<activity
android:name=".activities.EditProfileActivity"
android:label="@string/edit_profile"
android:theme="@style/AppThemeBarDark"
android:windowSoftInputMode="stateVisible" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<receiver
android:name=".broadcastreceiver.ToastMessage"
android:exported="false">
<intent-filter>
<action android:name="RECEIVE_TOAST_MESSAGE" />
</intent-filter>
</receiver>
<receiver
android:name=".services.CustomReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="org.unifiedpush.android.connector.MESSAGE" />
<action android:name="org.unifiedpush.android.connector.UNREGISTERED" />
<action android:name="org.unifiedpush.android.connector.NEW_ENDPOINT" />
<action android:name="org.unifiedpush.android.connector.REGISTRATION_FAILED" />
<action android:name="org.unifiedpush.android.connector.REGISTRATION_REFUSED" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@ -0,0 +1,13 @@
base_theme,2
author,Fedilab
name,Breeze Dark - Yellow
theme_boost_header_color,-14012878
theme_statuses_color,-14473687
theme_link_color,-12734743
theme_icons_color,-4340793
pref_color_background,-15658735
pref_color_navigation_bar,true
pref_color_status_bar,true
theme_accent,-148405
theme_text_color,-1052431
theme_primary,-13552069
1 base_theme 2
2 author Fedilab
3 name Breeze Dark - Yellow
4 theme_boost_header_color -14012878
5 theme_statuses_color -14473687
6 theme_link_color -12734743
7 theme_icons_color -4340793
8 pref_color_background -15658735
9 pref_color_navigation_bar true
10 pref_color_status_bar true
11 theme_accent -148405
12 theme_text_color -1052431
13 theme_primary -13552069

View File

@ -0,0 +1,15 @@
base_theme,2
author,Roboron
name,Cyberpunk Neon
theme_boost_header_color,-16776697,
theme_text_header_1_line,-1441575,
theme_text_header_2_line,-5242717,
theme_statuses_color,-16181197,
theme_link_color,-1441575,
theme_icons_color,-16138810,
pref_color_background,-16774370,
pref_color_navigation_bar,true,
pref_color_status_bar,true,
theme_accent,-1441575,
theme_text_color,-16138810,
theme_primary,-16774370,
1 base_theme,2
2 author,Roboron
3 name,Cyberpunk Neon
4 theme_boost_header_color,-16776697,
5 theme_text_header_1_line,-1441575,
6 theme_text_header_2_line,-5242717,
7 theme_statuses_color,-16181197,
8 theme_link_color,-1441575,
9 theme_icons_color,-16138810,
10 pref_color_background,-16774370,
11 pref_color_navigation_bar,true,
12 pref_color_status_bar,true,
13 theme_accent,-1441575,
14 theme_text_color,-16138810,
15 theme_primary,-16774370,

View File

@ -0,0 +1,15 @@
base_theme,2
author,Jøta Seth
name,Grey Orange
theme_boost_header_color,-14869219
theme_text_header_1_line,-1
theme_text_header_2_line,-1
theme_statuses_color,-14145496
theme_link_color,-26624
theme_icons_color,-26624
pref_color_background,-13092808
pref_color_navigation_bar,true
pref_color_status_bar,true
theme_accent,-26624
theme_text_color,-1
theme_primary,-14408668
1 base_theme 2
2 author Jøta Seth
3 name Grey Orange
4 theme_boost_header_color -14869219
5 theme_text_header_1_line -1
6 theme_text_header_2_line -1
7 theme_statuses_color -14145496
8 theme_link_color -26624
9 theme_icons_color -26624
10 pref_color_background -13092808
11 pref_color_navigation_bar true
12 pref_color_status_bar true
13 theme_accent -26624
14 theme_text_color -1
15 theme_primary -14408668

View File

@ -0,0 +1,15 @@
base_theme,2
author,@AntoineD@h.kher.nl
name,Gruvbox OLED
theme_boost_header_color,-16777216
theme_text_header_1_line,-265785
theme_text_header_2_line,-6777062
theme_statuses_color,-16777216
theme_link_color,-2647775
theme_icons_color,-7175308
pref_color_background,-16777216
pref_color_navigation_bar,true
pref_color_status_bar,true
theme_accent,-9921174
theme_text_color,-265785
theme_primary,-16777216
1 base_theme 2
2 author @AntoineD@h.kher.nl
3 name Gruvbox OLED
4 theme_boost_header_color -16777216
5 theme_text_header_1_line -265785
6 theme_text_header_2_line -6777062
7 theme_statuses_color -16777216
8 theme_link_color -2647775
9 theme_icons_color -7175308
10 pref_color_background -16777216
11 pref_color_navigation_bar true
12 pref_color_status_bar true
13 theme_accent -9921174
14 theme_text_color -265785
15 theme_primary -16777216

View File

@ -0,0 +1,15 @@
base_theme,2
author,AngryTux
name,Less Angry Orange
theme_boost_header_color,-15855063
theme_text_header_1_line,-2128640
theme_text_header_2_line,-5329234
theme_statuses_color,-1
theme_link_color,-12146699
theme_icons_color,-2128640
pref_color_background,-15987700
pref_color_navigation_bar,true
pref_color_status_bar,true
theme_accent,-3968000
theme_text_color,-197380
theme_primary,-14408668
1 base_theme 2
2 author AngryTux
3 name Less Angry Orange
4 theme_boost_header_color -15855063
5 theme_text_header_1_line -2128640
6 theme_text_header_2_line -5329234
7 theme_statuses_color -1
8 theme_link_color -12146699
9 theme_icons_color -2128640
10 pref_color_background -15987700
11 pref_color_navigation_bar true
12 pref_color_status_bar true
13 theme_accent -3968000
14 theme_text_color -197380
15 theme_primary -14408668

View File

@ -0,0 +1,15 @@
base_theme,2
author,Mondstern
name,Mondstern Fedilab
theme_boost_header_color,-1,
theme_text_header_1_line,-13855804,
theme_text_header_2_line,-16227945,
theme_statuses_color,-14935012,
theme_link_color,-15542685,
theme_icons_color,-10723999,
pref_color_background,-15921907,
pref_color_navigation_bar,false,
pref_color_status_bar,false,
theme_accent,-15542685,
theme_text_color,-1,
theme_primary,-14474461,
1 base_theme,2
2 author,Mondstern
3 name,Mondstern Fedilab
4 theme_boost_header_color,-1,
5 theme_text_header_1_line,-13855804,
6 theme_text_header_2_line,-16227945,
7 theme_statuses_color,-14935012,
8 theme_link_color,-15542685,
9 theme_icons_color,-10723999,
10 pref_color_background,-15921907,
11 pref_color_navigation_bar,false,
12 pref_color_status_bar,false,
13 theme_accent,-15542685,
14 theme_text_color,-1,
15 theme_primary,-14474461,

View File

@ -0,0 +1,13 @@
base_theme,2
author,Fedilab
name,Nocturnal
theme_boost_header_color,-12895429
theme_statuses_color,-13553359
theme_link_color,-16747570
theme_icons_color,-10158118
pref_color_background,-14606047
pref_color_navigation_bar,true
pref_color_status_bar,true
theme_accent,-13136013
theme_text_color,-2236963
theme_primary,-14013910
1 base_theme 2
2 author Fedilab
3 name Nocturnal
4 theme_boost_header_color -12895429
5 theme_statuses_color -13553359
6 theme_link_color -16747570
7 theme_icons_color -10158118
8 pref_color_background -14606047
9 pref_color_navigation_bar true
10 pref_color_status_bar true
11 theme_accent -13136013
12 theme_text_color -2236963
13 theme_primary -14013910

View File

@ -0,0 +1,15 @@
base_theme,2
author,Jøta Seth
name,Photon Dark
theme_boost_header_color,-14145496
theme_text_header_1_line,-1
theme_text_header_2_line,-1
theme_statuses_color,-14935012
theme_link_color,-14059009
theme_icons_color,-9474193
pref_color_background,-15921907
pref_color_navigation_bar,true
pref_color_status_bar,true
theme_accent,-14059009
theme_text_color,-1
theme_primary,-14474461
1 base_theme 2
2 author Jøta Seth
3 name Photon Dark
4 theme_boost_header_color -14145496
5 theme_text_header_1_line -1
6 theme_text_header_2_line -1
7 theme_statuses_color -14935012
8 theme_link_color -14059009
9 theme_icons_color -9474193
10 pref_color_background -15921907
11 pref_color_navigation_bar true
12 pref_color_status_bar true
13 theme_accent -14059009
14 theme_text_color -1
15 theme_primary -14474461

View File

@ -0,0 +1,15 @@
base_theme,2
author,Fedilab
name,Solarized Dark - Purple
theme_boost_header_color,-16506327
theme_text_header_1_line,-1120043
theme_text_header_2_line,-1120043
theme_statuses_color,-16304574
theme_link_color,-14251054
theme_icons_color,-7102047
pref_color_background,-16766154
pref_color_navigation_bar,true
pref_color_status_bar,true
theme_accent,-9670204
theme_text_color,-133405
theme_primary,-16304574
1 base_theme 2
2 author Fedilab
3 name Solarized Dark - Purple
4 theme_boost_header_color -16506327
5 theme_text_header_1_line -1120043
6 theme_text_header_2_line -1120043
7 theme_statuses_color -16304574
8 theme_link_color -14251054
9 theme_icons_color -7102047
10 pref_color_background -16766154
11 pref_color_navigation_bar true
12 pref_color_status_bar true
13 theme_accent -9670204
14 theme_text_color -133405
15 theme_primary -16304574

View File

@ -0,0 +1,47 @@
[
{
"theme_name": "Dark",
"base_theme": "DARK",
"primary": "#FF272727",
"primary_dark": "#FF272727",
"primary_light": "#FFd9e1e8",
"accent": "#FF2b90d9",
"accent_dark": "#FF1b80c9",
"accent_light": "#FF772b90d9",
"background": "#FF121212",
"background_dark": "#FF282c37",
"background_light": "#FF282c37",
"should_tint_statusbar": true,
"should_tint_navbar": true
},
{
"theme_name": "Light",
"base_theme": "LIGHT",
"primary": "#FFFFFF",
"primary_dark": "#FFFFFFFF",
"primary_light": "#FFd9e1e8",
"accent": "#FF2b90d9",
"accent_dark": "#FF1b80c9",
"accent_light": "#FF772b90d9",
"background": "#FFFFFFFF",
"background_dark": "#FFFFFFFF",
"background_light": "#FFFFFFFF",
"should_tint_statusbar": true,
"should_tint_navbar": true
},
{
"theme_name": "Black",
"base_theme": "DARK",
"primary": "#FF000000",
"primary_dark": "#FF000000",
"primary_light": "#FF000000",
"accent": "#FF606984",
"accent_dark": "#FF606984",
"accent_light": "#FF606984",
"background": "#FF000000",
"background_dark": "#FF000000",
"background_light": "#FF000000",
"should_tint_statusbar": true,
"should_tint_navbar": true
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,677 @@
package app.fedilab.android;
/* Copyright 2021 Thomas Schneider
*
* This file is a part of Fedilab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
import static app.fedilab.android.BaseMainActivity.status.DISCONNECTED;
import static app.fedilab.android.BaseMainActivity.status.UNKNOWN;
import static app.fedilab.android.helper.Helper.PREF_USER_TOKEN;
import static app.fedilab.android.helper.Helper.deleteDir;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.ContextThemeWrapper;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu;
import androidx.appcompat.widget.SearchView;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.view.GravityCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.preference.PreferenceManager;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.jaredrummler.cyanea.Cyanea;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.List;
import app.fedilab.android.activities.ActionActivity;
import app.fedilab.android.activities.BaseActivity;
import app.fedilab.android.activities.ComposeActivity;
import app.fedilab.android.activities.DraftActivity;
import app.fedilab.android.activities.FilterActivity;
import app.fedilab.android.activities.InstanceActivity;
import app.fedilab.android.activities.InstanceHealthActivity;
import app.fedilab.android.activities.LoginActivity;
import app.fedilab.android.activities.MainActivity;
import app.fedilab.android.activities.MastodonListActivity;
import app.fedilab.android.activities.ProfileActivity;
import app.fedilab.android.activities.ProxyActivity;
import app.fedilab.android.activities.ReorderTimelinesActivity;
import app.fedilab.android.activities.ScheduledActivity;
import app.fedilab.android.activities.SearchResultTabActivity;
import app.fedilab.android.activities.SettingsActivity;
import app.fedilab.android.broadcastreceiver.NetworkStateReceiver;
import app.fedilab.android.client.entities.Account;
import app.fedilab.android.client.entities.Pinned;
import app.fedilab.android.client.entities.app.PinnedTimeline;
import app.fedilab.android.client.mastodon.entities.Filter;
import app.fedilab.android.client.mastodon.entities.Instance;
import app.fedilab.android.client.mastodon.entities.MastodonList;
import app.fedilab.android.databinding.ActivityMainBinding;
import app.fedilab.android.databinding.NavHeaderMainBinding;
import app.fedilab.android.exception.DBException;
import app.fedilab.android.helper.Helper;
import app.fedilab.android.helper.PinnedTimelineHelper;
import app.fedilab.android.helper.PushHelper;
import app.fedilab.android.helper.ThemeHelper;
import app.fedilab.android.ui.fragment.timeline.FragmentMastodonTimeline;
import app.fedilab.android.viewmodel.mastodon.AccountsVM;
import app.fedilab.android.viewmodel.mastodon.InstancesVM;
import app.fedilab.android.viewmodel.mastodon.TimelinesVM;
import app.fedilab.android.viewmodel.mastodon.TopBarVM;
import es.dmoral.toasty.Toasty;
public abstract class BaseMainActivity extends BaseActivity implements NetworkStateReceiver.NetworkStateReceiverListener {
public static String currentInstance, currentToken, currentUserID, client_id, client_secret, software;
public static Account.API api;
public static boolean admin;
public static WeakReference<Account> accountWeakReference;
public static HashMap<Integer, Fragment> mPageReferenceMap;
public static status networkAvailable = UNKNOWN;
public static Instance instanceInfo;
public static List<Filter> mainFilters;
public static boolean filterFetched;
Fragment currentFragment;
private Account account;
private AppBarConfiguration mAppBarConfiguration;
private ActivityMainBinding binding;
private Pinned pinned;
private final BroadcastReceiver broadcast_data = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle b = intent.getExtras();
if (b != null) {
if (b.getBoolean(Helper.RECEIVE_REDRAW_TOPBAR, false)) {
List<MastodonList> mastodonLists = (List<MastodonList>) b.getSerializable(Helper.RECEIVE_MASTODON_LIST);
redrawPinned(mastodonLists);
} else if (b.getBoolean(Helper.RECEIVE_RECREATE_ACTIVITY, false)) {
Cyanea.getInstance().edit().apply().recreate(BaseMainActivity.this);
}
}
}
};
private NetworkStateReceiver networkStateReceiver;
private boolean headerMenuOpen;
protected abstract void rateThisApp();
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
mamageNewIntent(intent);
}
@SuppressLint("ApplySharedPref")
private void mamageNewIntent(Intent intent) {
if (intent == null)
return;
String action = intent.getAction();
String type = intent.getType();
Bundle extras = intent.getExtras();
String userIdIntent, instanceIntent;
if (extras != null && extras.containsKey(Helper.INTENT_ACTION)) {
userIdIntent = extras.getString(Helper.PREF_KEY_ID); //Id of the account in the intent
instanceIntent = extras.getString(Helper.PREF_INSTANCE);
if (extras.getInt(Helper.INTENT_ACTION) == Helper.NOTIFICATION_INTENT) {
try {
Account account = new Account(BaseMainActivity.this).getUniqAccount(userIdIntent, instanceIntent);
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(BaseMainActivity.this);
headerMenuOpen = false;
Toasty.info(BaseMainActivity.this, getString(R.string.toast_account_changed, "@" + account.mastodon_account.acct + "@" + account.instance), Toasty.LENGTH_LONG).show();
BaseMainActivity.currentToken = account.token;
BaseMainActivity.currentUserID = account.user_id;
api = account.api;
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(PREF_USER_TOKEN, account.token);
editor.commit();
Intent mainActivity = new Intent(this, MainActivity.class);
startActivity(mainActivity);
intent.removeExtra(Helper.INTENT_ACTION);
finish();
} catch (DBException e) {
e.printStackTrace();
}
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(BaseMainActivity.this);
ThemeHelper.applyTheme(this);
if (!Helper.isLoggedIn(BaseMainActivity.this)) {
//It is not, the user is redirected to the login page
Intent myIntent = new Intent(BaseMainActivity.this, LoginActivity.class);
startActivity(myIntent);
finish();
return;
} else {
BaseMainActivity.currentToken = sharedpreferences.getString(Helper.PREF_USER_TOKEN, null);
}
mamageNewIntent(getIntent());
ThemeHelper.initiliazeColors(BaseMainActivity.this);
filterFetched = false;
networkStateReceiver = new NetworkStateReceiver();
networkStateReceiver.addListener(this);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
ActionBar actionBar = getSupportActionBar();
//Remove title
if (actionBar != null) {
actionBar.setDisplayShowTitleEnabled(false);
}
rateThisApp();
SharedPreferences cyneaPref = getSharedPreferences("com.jaredrummler.cyanea", Context.MODE_PRIVATE);
binding.tabLayout.setTabTextColors(ThemeHelper.getAttColor(BaseMainActivity.this, R.attr.mTextColor), cyneaPref.getInt("theme_accent", -1));
binding.tabLayout.setTabIconTint(ThemeHelper.getColorStateList(BaseMainActivity.this));
binding.compose.setOnClickListener(v -> startActivity(new Intent(this, ComposeActivity.class)));
headerMenuOpen = false;
binding.bottomNavView.inflateMenu(R.menu.bottom_nav_menu);
binding.bottomNavView.setOnItemSelectedListener(item -> {
int itemId = item.getItemId();
if (itemId == R.id.nav_home) {
binding.viewPager.setCurrentItem(0);
} else if (itemId == R.id.nav_local) {
binding.viewPager.setCurrentItem(1);
} else if (itemId == R.id.nav_public) {
binding.viewPager.setCurrentItem(2);
} else if (itemId == R.id.nav_notifications) {
binding.viewPager.setCurrentItem(3);
} else if (itemId == R.id.nav_privates) {
binding.viewPager.setCurrentItem(4);
}
return true;
});
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder()
.setOpenableLayout(binding.drawerLayout)
.build();
NavHeaderMainBinding headerMainBinding = NavHeaderMainBinding.inflate(getLayoutInflater());
binding.navView.addHeaderView(headerMainBinding.getRoot());
binding.navView.setNavigationItemSelectedListener(menuItem -> {
int id = menuItem.getItemId();
if (id == R.id.nav_drafts) {
Intent intent = new Intent(this, DraftActivity.class);
startActivity(intent);
} else if (id == R.id.nav_reorder) {
Intent intent = new Intent(this, ReorderTimelinesActivity.class);
startActivity(intent);
} else if (id == R.id.nav_interactions) {
Intent intent = new Intent(this, ActionActivity.class);
startActivity(intent);
} else if (id == R.id.nav_filter) {
Intent intent = new Intent(this, FilterActivity.class);
startActivity(intent);
} else if (id == R.id.nav_list) {
Intent intent = new Intent(this, MastodonListActivity.class);
startActivity(intent);
} else if (id == R.id.nav_settings) {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
} else if (id == R.id.nav_scheduled) {
Intent intent = new Intent(this, ScheduledActivity.class);
startActivity(intent);
}
binding.drawerLayout.close();
return false;
});
headerMainBinding.instanceInfoContainer.setOnClickListener(v -> startActivity(new Intent(BaseMainActivity.this, InstanceHealthActivity.class)));
headerMainBinding.accountProfilePicture.setOnClickListener(v -> {
Intent intent = new Intent(BaseMainActivity.this, ProfileActivity.class);
Bundle b = new Bundle();
b.putSerializable(Helper.ARG_ACCOUNT, account.mastodon_account);
intent.putExtras(b);
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation(BaseMainActivity.this, headerMainBinding.instanceInfoContainer, getString(R.string.activity_porfile_pp));
startActivity(intent, options.toBundle());
});
headerMainBinding.changeAccount.setOnClickListener(v -> {
headerMenuOpen = !headerMenuOpen;
if (headerMenuOpen) {
headerMainBinding.ownerAccounts.setImageResource(R.drawable.ic_baseline_arrow_drop_up_24);
new Thread(() -> {
try {
List<Account> accounts = new Account(BaseMainActivity.this).getAll();
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> {
binding.navView.getMenu().clear();
binding.navView.inflateMenu(R.menu.menu_accounts);
headerMenuOpen = true;
Menu mainMenu = binding.navView.getMenu();
SubMenu currentSubmenu = null;
String lastInstance = "";
if (accounts != null) {
for (final Account account : accounts) {
if (!currentToken.equalsIgnoreCase(account.token)) {
if (!lastInstance.trim().equalsIgnoreCase(account.instance.trim())) {
lastInstance = account.instance.toUpperCase();
currentSubmenu = mainMenu.addSubMenu(account.instance.toUpperCase());
}
if (currentSubmenu == null) {
continue;
}
final MenuItem item = currentSubmenu.add("@" + account.mastodon_account.acct);
item.setIcon(R.drawable.ic_person);
boolean disableGif = sharedpreferences.getBoolean(getString(R.string.SET_DISABLE_GIF), false);
String url = !disableGif ? account.mastodon_account.avatar : account.mastodon_account.avatar_static;
if (url.startsWith("/")) {
url = "https://" + account.instance + account.mastodon_account.avatar;
}
if (!this.isDestroyed() && !this.isFinishing()) {
if (url.contains(".gif")) {
Glide.with(BaseMainActivity.this)
.asGif()
.load(url)
.into(new CustomTarget<GifDrawable>() {
@Override
public void onResourceReady(@NonNull GifDrawable resource, Transition<? super GifDrawable> transition) {
item.setIcon(resource);
item.getIcon().setColorFilter(0xFFFFFFFF, PorterDuff.Mode.MULTIPLY);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
} else {
Glide.with(BaseMainActivity.this)
.asDrawable()
.load(url)
.into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, Transition<? super Drawable> transition) {
item.setIcon(resource);
item.getIcon().setColorFilter(0xFFFFFFFF, PorterDuff.Mode.MULTIPLY);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
}
}
item.setOnMenuItemClickListener(item1 -> {
if (!this.isFinishing()) {
headerMenuOpen = false;
Toasty.info(BaseMainActivity.this, getString(R.string.toast_account_changed, "@" + account.mastodon_account.acct + "@" + account.instance), Toasty.LENGTH_LONG).show();
BaseMainActivity.currentToken = account.token;
BaseMainActivity.currentUserID = account.user_id;
api = account.api;
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(PREF_USER_TOKEN, account.token);
editor.commit();
//The user is now aut
//The user is now authenticated, it will be redirected to MainActivity
Intent mainActivity = new Intent(this, MainActivity.class);
startActivity(mainActivity);
finish();
headerMainBinding.ownerAccounts.setImageResource(R.drawable.ic_baseline_arrow_drop_down_24);
return true;
}
return false;
});
}
}
}
currentSubmenu = mainMenu.addSubMenu("");
MenuItem addItem = currentSubmenu.add(R.string.add_account);
addItem.setIcon(R.drawable.ic_baseline_person_add_24);
addItem.setOnMenuItemClickListener(item -> {
Intent intent = new Intent(BaseMainActivity.this, LoginActivity.class);
startActivity(intent);
return true;
});
};
mainHandler.post(myRunnable);
} catch (DBException e) {
e.printStackTrace();
}
}).start();
} else {
binding.navView.getMenu().clear();
binding.navView.inflateMenu(R.menu.activity_main_drawer);
headerMainBinding.ownerAccounts.setImageResource(R.drawable.ic_baseline_arrow_drop_down_24);
headerMenuOpen = false;
}
});
headerMainBinding.headerOptionInfo.setOnClickListener(v -> {
PopupMenu popup = new PopupMenu(new ContextThemeWrapper(BaseMainActivity.this, Helper.popupStyle()), headerMainBinding.headerOptionInfo);
popup.getMenuInflater()
.inflate(R.menu.main, popup.getMenu());
popup.setOnMenuItemClickListener(item -> {
int itemId = item.getItemId();
if (itemId == R.id.action_logout_account) {
AlertDialog.Builder alt_bld = new AlertDialog.Builder(BaseMainActivity.this, Helper.dialogStyle());
alt_bld.setTitle(R.string.action_logout);
alt_bld.setMessage(getString(R.string.logout_account_confirmation, account.mastodon_account.username, account.instance));
alt_bld.setPositiveButton(R.string.action_logout, (dialog, id) -> {
dialog.dismiss();
try {
Helper.removeAccount(BaseMainActivity.this, null);
} catch (DBException e) {
e.printStackTrace();
}
});
alt_bld.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
AlertDialog alert = alt_bld.create();
alert.show();
return true;
} else if (itemId == R.id.action_about_instance) {
Intent intent = new Intent(BaseMainActivity.this, InstanceActivity.class);
startActivity(intent);
return true;
} else if (itemId == R.id.action_cache) {
new Helper.CacheTask(BaseMainActivity.this);
return true;
} else if (itemId == R.id.action_proxy) {
Intent intent = new Intent(BaseMainActivity.this, ProxyActivity.class);
startActivity(intent);
return true;
}
return true;
});
popup.show();
});
account = null;
//Update account details
new Thread(() -> {
try {
account = new Account(BaseMainActivity.this).getConnectedAccount();
} catch (DBException e) {
e.printStackTrace();
}
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> {
if (account == null) {
//It is not, the user is redirected to the login page
Intent myIntent = new Intent(BaseMainActivity.this, LoginActivity.class);
startActivity(myIntent);
finish();
return;
}
currentInstance = account.instance;
currentUserID = account.user_id;
accountWeakReference = new WeakReference<>(account);
binding.profilePicture.setOnClickListener(v -> binding.drawerLayout.openDrawer(GravityCompat.START));
Helper.loadPP(binding.profilePicture, account);
headerMainBinding.accountAcc.setText(String.format("%s@%s", account.mastodon_account.username, account.instance));
if (account.mastodon_account.display_name.isEmpty()) {
account.mastodon_account.display_name = account.mastodon_account.acct;
}
headerMainBinding.accountName.setText(account.mastodon_account.display_name);
Helper.loadPP(headerMainBinding.accountProfilePicture, account);
/*
* Some general data are loaded when the app starts such;
* - Instance info (for limits)
* - Emoji for picker
* - Filters for timelines
* - Pinned timelines (in app feature)
*/
//Update emoji in db for the current instance
new ViewModelProvider(BaseMainActivity.this).get(InstancesVM.class).getEmoji(currentInstance);
//Retrieve instance info
new ViewModelProvider(BaseMainActivity.this).get(InstancesVM.class).getInstance(currentInstance)
.observe(BaseMainActivity.this, instance -> instanceInfo = instance.info);
//Retrieve filters
new ViewModelProvider(BaseMainActivity.this).get(AccountsVM.class).getFilters(currentInstance, currentToken)
.observe(BaseMainActivity.this, filters -> mainFilters = filters);
new ViewModelProvider(BaseMainActivity.this).get(AccountsVM.class).getConnectedAccount(currentInstance, currentToken)
.observe(BaseMainActivity.this, account1 -> {
BaseMainActivity.accountWeakReference.get().mastodon_account = account1;
});
//Update pinned timelines
new ViewModelProvider(BaseMainActivity.this).get(TopBarVM.class).getDBPinned()
.observe(this, pinned -> {
this.pinned = pinned;
//First it's taken from db (last stored values)
PinnedTimelineHelper.redrawTopBarPinned(BaseMainActivity.this, binding, pinned, null);
//Fetch remote lists for the authenticated account and update them
new ViewModelProvider(BaseMainActivity.this).get(TimelinesVM.class).getLists(currentInstance, currentToken)
.observe(this, mastodonLists -> PinnedTimelineHelper.redrawTopBarPinned(BaseMainActivity.this, binding, pinned, mastodonLists));
});
};
mainHandler.post(myRunnable);
}).start();
//Toolbar search
binding.toolbarSearch.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
//Hide keyboard
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(binding.toolbarSearch.getWindowToken(), 0);
query = query.replaceAll("^#+", "");
Intent intent;
intent = new Intent(BaseMainActivity.this, SearchResultTabActivity.class);
intent.putExtra(Helper.ARG_SEARCH_KEYWORD, query);
startActivity(intent);
binding.toolbarSearch.setQuery("", false);
binding.toolbarSearch.setIconified(true);
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
binding.toolbarSearch.setOnCloseListener(() -> {
binding.tabLayout.setVisibility(View.VISIBLE);
return false;
});
PushHelper.startStreaming(BaseMainActivity.this);
binding.toolbarSearch.setOnSearchClickListener(v -> binding.tabLayout.setVisibility(View.VISIBLE));
//For receiving data from other activities
LocalBroadcastManager.getInstance(BaseMainActivity.this).registerReceiver(broadcast_data, new IntentFilter(Helper.BROADCAST_DATA));
}
public void refreshFragment() {
if (binding.viewPager.getAdapter() != null) {
binding.viewPager.getAdapter().notifyDataSetChanged();
}
}
@Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(BaseMainActivity.this).unregisterReceiver(broadcast_data);
if (networkStateReceiver != null) {
try {
unregisterReceiver(networkStateReceiver);
} catch (IllegalArgumentException illegalArgumentException) {
illegalArgumentException.printStackTrace();
}
}
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(BaseMainActivity.this);
boolean clearCacheExit = sharedpreferences.getBoolean(getString(R.string.SET_CLEAR_CACHE_EXIT), false);
//Clear cache when leaving - Default = false
if (clearCacheExit) {
new Thread(() -> {
try {
if (getCacheDir().getParentFile() != null) {
String path = getCacheDir().getParentFile().getPath();
File dir = new File(path);
if (dir.isDirectory()) {
deleteDir(dir);
}
}
} catch (Exception ignored) {
}
}).start();
}
super.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
}
public void redrawPinned(List<MastodonList> mastodonLists) {
int currentItem = binding.viewPager.getCurrentItem();
new ViewModelProvider(BaseMainActivity.this).get(TopBarVM.class).getDBPinned()
.observe(this, pinned -> {
this.pinned = pinned;
//First it's taken from db (last stored values)
PinnedTimelineHelper.redrawTopBarPinned(BaseMainActivity.this, binding, pinned, mastodonLists);
binding.viewPager.setCurrentItem(currentItem);
});
}
@Override
public void onBackPressed() {
if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
binding.drawerLayout.closeDrawer(GravityCompat.START);
} else {
int fragments = getSupportFragmentManager().getBackStackEntryCount();
if (fragments == 1) {
finish();
} else if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
getSupportFragmentManager().popBackStack();
List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
for (Fragment fragment : fragmentList) {
if (fragment != null && fragment.isVisible()) {
if (fragment instanceof FragmentMastodonTimeline) {
currentFragment = fragment;
getSupportFragmentManager().beginTransaction().show(currentFragment).commit();
}
}
}
} else {
super.onBackPressed();
}
}
}
public boolean getFloatingVisibility() {
return binding.compose.getVisibility() == View.VISIBLE;
}
public void manageFloatingButton(boolean display) {
if (display) {
binding.compose.show();
} else {
binding.compose.hide();
}
}
/* @Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_logout) {
AlertDialog.Builder alt_bld = new AlertDialog.Builder(BaseMainActivity.this, Helper.dialogStyle());
alt_bld.setTitle(R.string.action_logout);
alt_bld.setMessage(getString(R.string.logout_account_confirmation, account.mastodon_account.username, account.instance));
alt_bld.setPositiveButton(R.string.action_logout, (dialog, id) -> {
dialog.dismiss();
try {
Helper.removeAccount(BaseMainActivity.this, null);
} catch (DBException e) {
e.printStackTrace();
}
});
alt_bld.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
AlertDialog alert = alt_bld.create();
alert.show();
}
return true;
}*/
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
//unselect all tag elements
for (PinnedTimeline pinnedTimeline : pinned.pinnedTimelines) {
pinnedTimeline.isSelected = false;
}
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
@Override
public void networkAvailable() {
networkAvailable = status.CONNECTED;
}
@Override
public void networkUnavailable() {
networkAvailable = DISCONNECTED;
}
public enum status {
UNKNOWN,
CONNECTED,
DISCONNECTED
}
}