initial commit
|
@ -0,0 +1,9 @@
|
||||||
|
*.iml
|
||||||
|
.gradle
|
||||||
|
/local.properties
|
||||||
|
/.idea/workspace.xml
|
||||||
|
/.idea/libraries
|
||||||
|
.DS_Store
|
||||||
|
/build
|
||||||
|
/captures
|
||||||
|
.externalNativeBuild
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CompilerConfiguration">
|
||||||
|
<resourceExtensions />
|
||||||
|
<wildcardResourcePatterns>
|
||||||
|
<entry name="!?*.java" />
|
||||||
|
<entry name="!?*.form" />
|
||||||
|
<entry name="!?*.class" />
|
||||||
|
<entry name="!?*.groovy" />
|
||||||
|
<entry name="!?*.scala" />
|
||||||
|
<entry name="!?*.flex" />
|
||||||
|
<entry name="!?*.kt" />
|
||||||
|
<entry name="!?*.clj" />
|
||||||
|
<entry name="!?*.aj" />
|
||||||
|
</wildcardResourcePatterns>
|
||||||
|
<annotationProcessing>
|
||||||
|
<profile default="true" name="Default" enabled="false">
|
||||||
|
<processorPath useClasspath="true" />
|
||||||
|
</profile>
|
||||||
|
</annotationProcessing>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<component name="CopyrightManager">
|
||||||
|
<settings default="" />
|
||||||
|
</component>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="GradleSettings">
|
||||||
|
<option name="linkedExternalProjectsSettings">
|
||||||
|
<GradleProjectSettings>
|
||||||
|
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="modules">
|
||||||
|
<set>
|
||||||
|
<option value="$PROJECT_DIR$" />
|
||||||
|
<option value="$PROJECT_DIR$/app" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
|
</GradleProjectSettings>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<component name="MarkdownNavigator.ProfileManager">
|
||||||
|
<settings default="" pdf-export="" />
|
||||||
|
</component>
|
|
@ -0,0 +1,129 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="EntryPointsManager">
|
||||||
|
<entry_points version="2.0" />
|
||||||
|
</component>
|
||||||
|
<component name="MarkdownProjectSettings">
|
||||||
|
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="LINE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="true" showSelectionInPreview="true">
|
||||||
|
<PanelProvider>
|
||||||
|
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
|
||||||
|
</PanelProvider>
|
||||||
|
</PreviewSettings>
|
||||||
|
<ParserSettings>
|
||||||
|
<PegdownExtensions>
|
||||||
|
<option name="ABBREVIATIONS" value="false" />
|
||||||
|
<option name="ANCHORLINKS" value="true" />
|
||||||
|
<option name="ASIDE" value="false" />
|
||||||
|
<option name="ATXHEADERSPACE" value="true" />
|
||||||
|
<option name="AUTOLINKS" value="true" />
|
||||||
|
<option name="DEFINITIONS" value="false" />
|
||||||
|
<option name="FENCED_CODE_BLOCKS" value="true" />
|
||||||
|
<option name="FOOTNOTES" value="false" />
|
||||||
|
<option name="HARDWRAPS" value="false" />
|
||||||
|
<option name="INSERTED" value="false" />
|
||||||
|
<option name="QUOTES" value="false" />
|
||||||
|
<option name="RELAXEDHRULES" value="true" />
|
||||||
|
<option name="SMARTS" value="false" />
|
||||||
|
<option name="STRIKETHROUGH" value="true" />
|
||||||
|
<option name="SUBSCRIPT" value="false" />
|
||||||
|
<option name="SUPERSCRIPT" value="false" />
|
||||||
|
<option name="SUPPRESS_HTML_BLOCKS" value="false" />
|
||||||
|
<option name="SUPPRESS_INLINE_HTML" value="false" />
|
||||||
|
<option name="TABLES" value="true" />
|
||||||
|
<option name="TASKLISTITEMS" value="true" />
|
||||||
|
<option name="TOC" value="false" />
|
||||||
|
<option name="WIKILINKS" value="true" />
|
||||||
|
</PegdownExtensions>
|
||||||
|
<ParserOptions>
|
||||||
|
<option name="COMMONMARK_LISTS" value="false" />
|
||||||
|
<option name="DUMMY" value="false" />
|
||||||
|
<option name="EMOJI_SHORTCUTS" value="true" />
|
||||||
|
<option name="FLEXMARK_FRONT_MATTER" value="false" />
|
||||||
|
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
|
||||||
|
<option name="GFM_TABLE_RENDERING" value="true" />
|
||||||
|
<option name="GITBOOK_URL_ENCODING" value="false" />
|
||||||
|
<option name="GITHUB_EMOJI_URL" value="false" />
|
||||||
|
<option name="GITHUB_LISTS" value="true" />
|
||||||
|
<option name="GITHUB_WIKI_LINKS" value="true" />
|
||||||
|
<option name="JEKYLL_FRONT_MATTER" value="false" />
|
||||||
|
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
|
||||||
|
</ParserOptions>
|
||||||
|
</ParserSettings>
|
||||||
|
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true">
|
||||||
|
<GeneratorProvider>
|
||||||
|
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
|
||||||
|
</GeneratorProvider>
|
||||||
|
<headerTop />
|
||||||
|
<headerBottom />
|
||||||
|
<bodyTop />
|
||||||
|
<bodyBottom />
|
||||||
|
</HtmlSettings>
|
||||||
|
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssTextEnabled="false" isDynamicPageWidth="true">
|
||||||
|
<StylesheetProvider>
|
||||||
|
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
|
||||||
|
</StylesheetProvider>
|
||||||
|
<ScriptProviders />
|
||||||
|
<cssText />
|
||||||
|
</CssSettings>
|
||||||
|
<HtmlExportSettings updateOnSave="false" parentDir="$ProjectFileDir$" targetDir="$ProjectFileDir$" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetExt="" useTargetExt="false" noCssNoScripts="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" />
|
||||||
|
<LinkMapSettings>
|
||||||
|
<textMaps />
|
||||||
|
</LinkMapSettings>
|
||||||
|
</component>
|
||||||
|
<component name="NullableNotNullManager">
|
||||||
|
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||||
|
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||||
|
<option name="myNullables">
|
||||||
|
<value>
|
||||||
|
<list size="4">
|
||||||
|
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||||
|
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||||
|
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||||
|
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="myNotNulls">
|
||||||
|
<value>
|
||||||
|
<list size="4">
|
||||||
|
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||||
|
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||||
|
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||||
|
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||||
|
<OptionsSetting value="true" id="Add" />
|
||||||
|
<OptionsSetting value="true" id="Remove" />
|
||||||
|
<OptionsSetting value="true" id="Checkout" />
|
||||||
|
<OptionsSetting value="true" id="Update" />
|
||||||
|
<OptionsSetting value="true" id="Status" />
|
||||||
|
<OptionsSetting value="true" id="Edit" />
|
||||||
|
<ConfirmationsSetting value="0" id="Add" />
|
||||||
|
<ConfirmationsSetting value="0" id="Remove" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectType">
|
||||||
|
<option name="id" value="Android" />
|
||||||
|
</component>
|
||||||
|
<component name="masterDetails">
|
||||||
|
<states>
|
||||||
|
<state key="ProjectJDKs.UI">
|
||||||
|
<settings>
|
||||||
|
<last-edited>1.8</last-edited>
|
||||||
|
<splitter-proportions>
|
||||||
|
<option name="proportions">
|
||||||
|
<list>
|
||||||
|
<option value="0.2" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</splitter-proportions>
|
||||||
|
</settings>
|
||||||
|
</state>
|
||||||
|
</states>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/Mastodon.iml" filepath="$PROJECT_DIR$/Mastodon.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RunConfigurationProducerService">
|
||||||
|
<option name="ignoredProducers">
|
||||||
|
<set>
|
||||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
|
@ -0,0 +1,37 @@
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 25
|
||||||
|
buildToolsVersion "25.0.2"
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "fr.gouv.etalab.mastodon"
|
||||||
|
minSdkVersion 15
|
||||||
|
targetSdkVersion 25
|
||||||
|
versionCode 2
|
||||||
|
versionName "1.0.2"
|
||||||
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
|
||||||
|
exclude group: 'com.android.support', module: 'support-annotations'
|
||||||
|
})
|
||||||
|
compile 'com.android.support:appcompat-v7:25.3.1'
|
||||||
|
compile 'com.android.support:design:25.3.1'
|
||||||
|
compile 'com.android.support:support-v4:25.3.1'
|
||||||
|
compile 'com.android.support.constraint:constraint-layout:1.0.0-beta4'
|
||||||
|
compile 'com.loopj.android:android-async-http:1.4.9'
|
||||||
|
compile 'com.google.code.gson:gson:2.8.0'
|
||||||
|
compile 'com.squareup.retrofit2:retrofit:2.2.0'
|
||||||
|
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
||||||
|
compile 'com.evernote:android-job:1.1.9'
|
||||||
|
testCompile 'junit:junit:4.12'
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in /Users/Thomas/Library/Android/sdk/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the proguardFiles
|
||||||
|
# directive in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# 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
|
|
@ -0,0 +1,26 @@
|
||||||
|
package mastodon.etalab.gouv.fr.mastodon;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.test.InstrumentationRegistry;
|
||||||
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumentation 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() throws Exception {
|
||||||
|
// Context of the app under test.
|
||||||
|
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||||
|
|
||||||
|
assertEquals("mastodon.etalab.gouv.fr.mastodon", appContext.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2017 Thomas Schneider
|
||||||
|
|
||||||
|
This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
see <http://www.gnu.org/licenses>
|
||||||
|
-->
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:installLocation="auto"
|
||||||
|
package="mastodon.etalab.gouv.fr.mastodon">
|
||||||
|
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:name="fr.gouv.etalab.mastodon.activities.MainApplication"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
<activity
|
||||||
|
android:name="fr.gouv.etalab.mastodon.activities.MainActivity"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:windowSoftInputMode="stateAlwaysHidden"
|
||||||
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
|
android:theme="@style/AppTheme.NoActionBar">
|
||||||
|
</activity>
|
||||||
|
<activity android:name="fr.gouv.etalab.mastodon.activities.WebviewActivity"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
/>
|
||||||
|
<activity android:name="fr.gouv.etalab.mastodon.activities.LoginActivity"
|
||||||
|
android:windowSoftInputMode="stateAlwaysHidden"
|
||||||
|
android:configChanges="orientation|screenSize"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
/>
|
||||||
|
<activity android:name="fr.gouv.etalab.mastodon.activities.ShowAccountActivity"
|
||||||
|
android:windowSoftInputMode="stateAlwaysHidden"
|
||||||
|
android:configChanges="orientation|screenSize"
|
||||||
|
android:noHistory="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
/>
|
||||||
|
<activity android:name="fr.gouv.etalab.mastodon.activities.ShowConversationActivity"
|
||||||
|
android:windowSoftInputMode="stateAlwaysHidden"
|
||||||
|
android:configChanges="orientation|screenSize"
|
||||||
|
android:noHistory="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
/>
|
||||||
|
<activity android:name="fr.gouv.etalab.mastodon.activities.AboutActivity"
|
||||||
|
android:windowSoftInputMode="stateAlwaysHidden"
|
||||||
|
android:configChanges="orientation|screenSize"
|
||||||
|
android:noHistory="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
/>
|
||||||
|
<activity android:name="fr.gouv.etalab.mastodon.activities.TootActivity"
|
||||||
|
android:windowSoftInputMode="adjustResize"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:configChanges="orientation|screenSize"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
/>
|
||||||
|
<activity
|
||||||
|
android:name="fr.gouv.etalab.mastodon.activities.SplashActivity"
|
||||||
|
android:theme="@style/SplashTheme">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
After Width: | Height: | Size: 52 KiB |
|
@ -0,0 +1,75 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.activities;
|
||||||
|
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.method.LinkMovementMethod;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 05/05/2017.
|
||||||
|
* About activity
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class AboutActivity extends AppCompatActivity {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if( getSupportActionBar() != null)
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
setContentView(R.layout.activity_about);
|
||||||
|
TextView about_version = (TextView) findViewById(R.id.about_version);
|
||||||
|
try {
|
||||||
|
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
|
||||||
|
String version = pInfo.versionName;
|
||||||
|
about_version.setText(getResources().getString(R.string.about_vesrion, version));
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView about_developer = (TextView) findViewById(R.id.about_developer);
|
||||||
|
TextView about_license = (TextView) findViewById(R.id.about_license);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
about_developer.setText(Html.fromHtml(getString(R.string.about_developer), Html.FROM_HTML_MODE_COMPACT));
|
||||||
|
about_license.setText(Html.fromHtml(getString(R.string.about_license), Html.FROM_HTML_MODE_COMPACT));
|
||||||
|
|
||||||
|
}else {
|
||||||
|
about_developer.setText(Html.fromHtml(getString(R.string.about_developer)));
|
||||||
|
about_license.setText(Html.fromHtml(getString(R.string.about_license)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.activities;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.loopj.android.http.AsyncHttpResponseHandler;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import cz.msebera.android.httpclient.Header;
|
||||||
|
import fr.gouv.etalab.mastodon.client.OauthClient;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
* Login activity class which handles the connection
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class LoginActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_login);
|
||||||
|
|
||||||
|
final Button connectionButton = (Button) findViewById(R.id.login_button);
|
||||||
|
final Intent webviewIntent = new Intent(this, WebviewActivity.class);
|
||||||
|
|
||||||
|
|
||||||
|
connectionButton.setEnabled(false);
|
||||||
|
|
||||||
|
String action = "/api/v1/apps";
|
||||||
|
HashMap<String,String> parameters = new HashMap<>();
|
||||||
|
parameters.put(Helper.CLIENT_NAME, Helper.OAUTH_REDIRECT_HOST);
|
||||||
|
parameters.put(Helper.REDIRECT_URIS,"https://" + Helper.INSTANCE + Helper.REDIRECT_CONTENT);
|
||||||
|
parameters.put(Helper.SCOPES, Helper.OAUTH_SCOPES);
|
||||||
|
parameters.put(Helper.WEBSITE,"https://" + Helper.INSTANCE);
|
||||||
|
new OauthClient().post(action, parameters, new AsyncHttpResponseHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
|
||||||
|
String response = new String(responseBody);
|
||||||
|
JSONObject resobj;
|
||||||
|
try {
|
||||||
|
resobj = new JSONObject(response);
|
||||||
|
String client_id = resobj.get(Helper.CLIENT_ID).toString();
|
||||||
|
String client_secret = resobj.get(Helper.CLIENT_SECRET).toString();
|
||||||
|
|
||||||
|
String id = resobj.get(Helper.ID).toString();
|
||||||
|
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putString(Helper.CLIENT_ID, client_id);
|
||||||
|
editor.putString(Helper.CLIENT_SECRET, client_secret);
|
||||||
|
editor.putString(Helper.ID, id);
|
||||||
|
editor.apply();
|
||||||
|
connectionButton.setEnabled(true);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
|
||||||
|
error.printStackTrace();
|
||||||
|
Toast.makeText(LoginActivity.this,R.string.client_error, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connectionButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
startActivity(webviewIntent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,424 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.activities;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.design.widget.FloatingActionButton;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.support.design.widget.NavigationView;
|
||||||
|
import android.support.v4.view.GravityCompat;
|
||||||
|
import android.support.v4.widget.DrawerLayout;
|
||||||
|
import android.support.v7.app.ActionBarDrawerToggle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
|
||||||
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
||||||
|
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.fragments.DisplayAccountsFragment;
|
||||||
|
import fr.gouv.etalab.mastodon.fragments.DisplayNotificationsFragment;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnUpdateAccountInfoInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.UpdateAccountInfoAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.fragments.DisplayStatusFragment;
|
||||||
|
import fr.gouv.etalab.mastodon.fragments.TabLayoutSettingsFragment;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
|
||||||
|
import static fr.gouv.etalab.mastodon.helper.Helper.INTENT_ACTION;
|
||||||
|
import static fr.gouv.etalab.mastodon.helper.Helper.INTENT_NOTIFICATION;
|
||||||
|
|
||||||
|
public class MainActivity extends AppCompatActivity
|
||||||
|
implements NavigationView.OnNavigationItemSelectedListener, OnUpdateAccountInfoInterface {
|
||||||
|
|
||||||
|
private FloatingActionButton toot;
|
||||||
|
private boolean first = true;
|
||||||
|
private HashMap<String, String> tagTile = new HashMap<>();
|
||||||
|
private HashMap<String, Integer> tagItem = new HashMap<>();
|
||||||
|
private Toolbar toolbar;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
//Test if user is still log in
|
||||||
|
if( ! Helper.isLoggedIn(getApplicationContext())) {
|
||||||
|
//It is not, the user is redirected to the login page
|
||||||
|
Intent myIntent = new Intent(MainActivity.this, LoginActivity.class);
|
||||||
|
startActivity(myIntent);
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Here, the user is authenticated
|
||||||
|
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
|
toot = (FloatingActionButton) findViewById(R.id.toot);
|
||||||
|
toot.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Intent intent = new Intent(getApplicationContext(), TootActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||||
|
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
|
||||||
|
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
|
||||||
|
drawer.setDrawerListener(toggle);
|
||||||
|
toggle.syncState();
|
||||||
|
|
||||||
|
final NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
|
||||||
|
navigationView.setNavigationItemSelectedListener(this);
|
||||||
|
|
||||||
|
|
||||||
|
//Image loader configuration
|
||||||
|
ImageLoader imageLoader;
|
||||||
|
imageLoader = ImageLoader.getInstance();
|
||||||
|
File cacheDir = new File(getCacheDir(), getString(R.string.app_name));
|
||||||
|
ImageLoaderConfiguration configImg = new ImageLoaderConfiguration.Builder(this)
|
||||||
|
.threadPoolSize(5)
|
||||||
|
.threadPriority(Thread.MIN_PRIORITY + 3)
|
||||||
|
.denyCacheImageMultipleSizesInMemory()
|
||||||
|
.diskCache(new UnlimitedDiskCache(cacheDir))
|
||||||
|
.build();
|
||||||
|
imageLoader.init(configImg);
|
||||||
|
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||||
|
DisplayImageOptions options = new DisplayImageOptions.Builder().displayer(new RoundedBitmapDisplayer(90)).cacheInMemory(false)
|
||||||
|
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
|
||||||
|
|
||||||
|
|
||||||
|
View headerLayout = navigationView.getHeaderView(0);
|
||||||
|
|
||||||
|
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
String prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
|
||||||
|
Account account = new AccountDAO(getApplicationContext(), db).getAccountByToken(prefKeyOauthTokenT);
|
||||||
|
ImageView profilePicture = (ImageView) headerLayout.findViewById(R.id.profilePicture);
|
||||||
|
TextView username = (TextView) headerLayout.findViewById(R.id.username);
|
||||||
|
TextView displayedName = (TextView) headerLayout.findViewById(R.id.displayedName);
|
||||||
|
TextView ownerStatus = (TextView) headerLayout.findViewById(R.id.owner_status);
|
||||||
|
TextView ownerFollowing = (TextView) headerLayout.findViewById(R.id.owner_following);
|
||||||
|
TextView ownerFollowers = (TextView) headerLayout.findViewById(R.id.owner_followers);
|
||||||
|
|
||||||
|
ownerStatus.setText(String.valueOf(account.getStatuses_count()));
|
||||||
|
ownerFollowers.setText(String.valueOf(account.getFollowers_count()));
|
||||||
|
ownerFollowing.setText(String.valueOf(account.getFollowing_count()));
|
||||||
|
username.setText(String.format("@%s",account.getUsername()));
|
||||||
|
displayedName.setText(account.getDisplay_name());
|
||||||
|
imageLoader.displayImage(account.getAvatar(), profilePicture, options);
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
navigationView.setCheckedItem(R.id.nav_home);
|
||||||
|
navigationView.getMenu().performIdentifierAction(R.id.nav_home, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
//Title and menu selection when back pressed
|
||||||
|
getSupportFragmentManager().addOnBackStackChangedListener(
|
||||||
|
new FragmentManager.OnBackStackChangedListener() {
|
||||||
|
public void onBackStackChanged() {
|
||||||
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
|
if( fm != null && fm.getBackStackEntryCount() > 0) {
|
||||||
|
String fragmentTag = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1).getName();
|
||||||
|
if( fragmentTag != null) {
|
||||||
|
if( tagTile.get(fragmentTag) != null)
|
||||||
|
setTitle(tagTile.get(fragmentTag));
|
||||||
|
if( tagItem.get(fragmentTag) != null) {
|
||||||
|
unCheckAllMenuItems(navigationView.getMenu());
|
||||||
|
if( navigationView.getMenu().findItem(tagItem.get(fragmentTag)) != null)
|
||||||
|
navigationView.getMenu().findItem(tagItem.get(fragmentTag)).setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unCheckAllMenuItems(@NonNull final Menu menu) {
|
||||||
|
int size = menu.size();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
final MenuItem item = menu.getItem(i);
|
||||||
|
if(item.hasSubMenu()) {
|
||||||
|
unCheckAllMenuItems(item.getSubMenu());
|
||||||
|
} else {
|
||||||
|
item.setChecked(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onNewIntent(Intent intent) {
|
||||||
|
super.onNewIntent(intent);
|
||||||
|
if( intent == null || intent.getExtras() == null )
|
||||||
|
return;
|
||||||
|
Bundle extras = intent.getExtras();
|
||||||
|
if( extras.containsKey(INTENT_ACTION) ){
|
||||||
|
if (extras.getInt(INTENT_ACTION) == INTENT_NOTIFICATION){
|
||||||
|
final NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
|
||||||
|
navigationView.setCheckedItem(R.id.nav_notification);
|
||||||
|
navigationView.getMenu().performIdentifierAction(R.id.nav_notification, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
intent.replaceExtras(new Bundle());
|
||||||
|
intent.setAction("");
|
||||||
|
intent.setData(null);
|
||||||
|
intent.setFlags(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||||
|
if (drawer.isDrawerOpen(GravityCompat.START)) {
|
||||||
|
drawer.closeDrawer(GravityCompat.START);
|
||||||
|
} else {
|
||||||
|
super.onBackPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(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) {
|
||||||
|
// Handle action bar item clicks here. The action bar will
|
||||||
|
// automatically handle clicks on the Home/Up button, so long
|
||||||
|
// as you specify a parent activity in AndroidManifest.xml.
|
||||||
|
int id = item.getItemId();
|
||||||
|
|
||||||
|
//noinspection SimplifiableIfStatement
|
||||||
|
if(id == R.id.action_logout) {
|
||||||
|
Helper.logout(getApplicationContext());
|
||||||
|
Intent myIntent = new Intent(MainActivity.this, LoginActivity.class);
|
||||||
|
startActivity(myIntent);
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
}else if(id == R.id.action_about){
|
||||||
|
Intent intent = new Intent(getApplicationContext(), AboutActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
}else if(id == R.id.action_search){
|
||||||
|
|
||||||
|
if( toolbar.getChildCount() > 0){
|
||||||
|
for(int i = 0 ; i < toolbar.getChildCount() ; i++){
|
||||||
|
if(toolbar.getChildAt(i) instanceof EditText){
|
||||||
|
//Nothing in the search bar
|
||||||
|
if( ((EditText) toolbar.getChildAt(i)).getText().toString().trim().equals("")){
|
||||||
|
toolbar.removeViewAt(i);
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
String searchTag = ((EditText) toolbar.getChildAt(i)).getText().toString();
|
||||||
|
toot.setVisibility(View.VISIBLE);
|
||||||
|
DisplayStatusFragment statusFragment = new DisplayStatusFragment();
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.TAG);
|
||||||
|
bundle.putString("tag", searchTag);
|
||||||
|
statusFragment.setArguments(bundle);
|
||||||
|
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.main_app_container, statusFragment).commit();
|
||||||
|
View view = this.getCurrentFocus();
|
||||||
|
//Hide keyboard
|
||||||
|
if (view != null) {
|
||||||
|
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Open the search bar
|
||||||
|
EditText search = new EditText(getApplicationContext());
|
||||||
|
search.setSingleLine(true);
|
||||||
|
search.setLayoutParams( new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT,1.0f));
|
||||||
|
toolbar.addView(search);
|
||||||
|
search.requestFocus();
|
||||||
|
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume(){
|
||||||
|
super.onResume();
|
||||||
|
//Proceeds to update of the authenticated account
|
||||||
|
if(Helper.isLoggedIn(getApplicationContext()))
|
||||||
|
new UpdateAccountInfoAsyncTask(getApplicationContext(), null, MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("StatementWithEmptyBody")
|
||||||
|
@Override
|
||||||
|
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
||||||
|
// Handle navigation view item clicks here.
|
||||||
|
int id = item.getItemId();
|
||||||
|
//Remove the search bar
|
||||||
|
if( toolbar.getChildCount() > 0) {
|
||||||
|
for (int i = 0; i < toolbar.getChildCount(); i++) {
|
||||||
|
if (toolbar.getChildAt(i) instanceof EditText) {
|
||||||
|
toolbar.removeViewAt(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DisplayStatusFragment statusFragment;
|
||||||
|
DisplayAccountsFragment accountsFragment;
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||||
|
String fragmentTag = null;
|
||||||
|
if (id == R.id.nav_home) {
|
||||||
|
toot.setVisibility(View.VISIBLE);
|
||||||
|
statusFragment = new DisplayStatusFragment();
|
||||||
|
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.HOME);
|
||||||
|
statusFragment.setArguments(bundle);
|
||||||
|
fragmentTag = "HOME_TIMELINE";
|
||||||
|
if(! first)
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.main_app_container, statusFragment, fragmentTag).addToBackStack(fragmentTag).commit();
|
||||||
|
else{
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.main_app_container, statusFragment, fragmentTag).commit();
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
} else if (id == R.id.nav_local) {
|
||||||
|
toot.setVisibility(View.VISIBLE);
|
||||||
|
statusFragment = new DisplayStatusFragment();
|
||||||
|
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.LOCAL);
|
||||||
|
statusFragment.setArguments(bundle);
|
||||||
|
fragmentTag = "LOCAL_TIMELINE";
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.main_app_container, statusFragment, fragmentTag).addToBackStack(fragmentTag).commit();
|
||||||
|
|
||||||
|
} else if (id == R.id.nav_global) {
|
||||||
|
toot.setVisibility(View.VISIBLE);
|
||||||
|
statusFragment = new DisplayStatusFragment();
|
||||||
|
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.PUBLIC);
|
||||||
|
statusFragment.setArguments(bundle);
|
||||||
|
fragmentTag = "PUBLIC_TIMELINE";
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.main_app_container, statusFragment, fragmentTag).addToBackStack(fragmentTag).commit();
|
||||||
|
} else if (id == R.id.nav_settings) {
|
||||||
|
toot.setVisibility(View.GONE);
|
||||||
|
TabLayoutSettingsFragment tabLayoutSettingsFragment= new TabLayoutSettingsFragment();
|
||||||
|
fragmentTag = "TABLAYOUT_SETTINGS";
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.main_app_container, tabLayoutSettingsFragment, fragmentTag).addToBackStack(fragmentTag).commit();
|
||||||
|
|
||||||
|
} else if (id == R.id.nav_favorites) {
|
||||||
|
toot.setVisibility(View.GONE);
|
||||||
|
statusFragment = new DisplayStatusFragment();
|
||||||
|
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.FAVOURITES);
|
||||||
|
statusFragment.setArguments(bundle);
|
||||||
|
fragmentTag = "FAVOURITES";
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.main_app_container, statusFragment, fragmentTag).addToBackStack(fragmentTag).commit();
|
||||||
|
} else if (id == R.id.nav_blocked) {
|
||||||
|
toot.setVisibility(View.GONE);
|
||||||
|
accountsFragment = new DisplayAccountsFragment();
|
||||||
|
bundle.putSerializable("type", RetrieveAccountsAsyncTask.Type.BLOCKED);
|
||||||
|
accountsFragment.setArguments(bundle);
|
||||||
|
fragmentTag = "BLOCKS";
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.main_app_container, accountsFragment, fragmentTag).addToBackStack(fragmentTag).commit();
|
||||||
|
}else if (id == R.id.nav_muted) {
|
||||||
|
toot.setVisibility(View.GONE);
|
||||||
|
accountsFragment = new DisplayAccountsFragment();
|
||||||
|
bundle.putSerializable("type", RetrieveAccountsAsyncTask.Type.MUTED);
|
||||||
|
accountsFragment.setArguments(bundle);
|
||||||
|
fragmentTag = "BLOCKS";
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.main_app_container, accountsFragment, fragmentTag).addToBackStack(fragmentTag).commit();
|
||||||
|
}else if( id == R.id.nav_notification){
|
||||||
|
toot.setVisibility(View.GONE);
|
||||||
|
DisplayNotificationsFragment notificationsFragment = new DisplayNotificationsFragment();
|
||||||
|
fragmentTag = "NOTIFICATIONS";
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.replace(R.id.main_app_container, notificationsFragment, fragmentTag).addToBackStack(fragmentTag).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setTitle(item.getTitle());
|
||||||
|
populateTitleWithTag(fragmentTag, item.getTitle().toString(), item.getItemId());
|
||||||
|
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||||
|
drawer.closeDrawer(GravityCompat.START);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populateTitleWithTag(String tag, String title, int index){
|
||||||
|
if( tag == null)
|
||||||
|
return;
|
||||||
|
if ( tagTile.get(tag) == null)
|
||||||
|
tagTile.put(tag, title);
|
||||||
|
if ( tagItem.get(tag) == null)
|
||||||
|
tagItem.put(tag, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTitle(CharSequence title) {
|
||||||
|
if( getSupportActionBar() != null )
|
||||||
|
getSupportActionBar().setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdateAccountInfo(boolean error) {
|
||||||
|
if( error){
|
||||||
|
//It is not, the user is redirected to the login page
|
||||||
|
Helper.logout(getApplicationContext());
|
||||||
|
Intent myIntent = new Intent(MainActivity.this, LoginActivity.class);
|
||||||
|
startActivity(myIntent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package fr.gouv.etalab.mastodon.activities;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import com.evernote.android.job.JobManager;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.jobs.ApplicationJob;
|
||||||
|
import fr.gouv.etalab.mastodon.jobs.NotificationsSyncJob;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 29/04/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MainApplication extends Application{
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
JobManager.create(this).addJobCreator(new ApplicationJob());
|
||||||
|
JobManager.instance().getConfig().setVerbose(false);
|
||||||
|
NotificationsSyncJob.schedule(getApplicationContext(), false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,307 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.activities;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.design.widget.TabLayout;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||||
|
import android.support.v4.view.PagerAdapter;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.PostActionAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveRelationshipAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Status;
|
||||||
|
import fr.gouv.etalab.mastodon.drawers.StatusListAdapter;
|
||||||
|
import fr.gouv.etalab.mastodon.fragments.DisplayAccountsFragment;
|
||||||
|
import fr.gouv.etalab.mastodon.fragments.DisplayStatusFragment;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAccountInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsAccountInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveRelationshipInterface;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Relationship;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 01/05/2017.
|
||||||
|
* Show account activity class
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ShowAccountActivity extends AppCompatActivity implements OnPostActionInterface, OnRetrieveAccountInterface, OnRetrieveFeedsAccountInterface, OnRetrieveRelationshipInterface {
|
||||||
|
|
||||||
|
|
||||||
|
private ImageLoader imageLoader;
|
||||||
|
private DisplayImageOptions options;
|
||||||
|
private List<Status> statuses;
|
||||||
|
private StatusListAdapter statusListAdapter;
|
||||||
|
private Button account_follow;
|
||||||
|
|
||||||
|
private static final int NUM_PAGES = 3;
|
||||||
|
private ViewPager mPager;
|
||||||
|
private String accountId;
|
||||||
|
private TabLayout tabLayout;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public enum action{
|
||||||
|
FOLLOW,
|
||||||
|
UNFOLLOW,
|
||||||
|
UNBLOCK,
|
||||||
|
NOTHING
|
||||||
|
}
|
||||||
|
|
||||||
|
private action doAction;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_show_account);
|
||||||
|
|
||||||
|
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
imageLoader = ImageLoader.getInstance();
|
||||||
|
statuses = new ArrayList<>();
|
||||||
|
boolean isOnWifi = Helper.isOnWIFI(getApplicationContext());
|
||||||
|
int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
|
||||||
|
statusListAdapter = new StatusListAdapter(getApplicationContext(), RetrieveFeedsAsyncTask.Type.USER, isOnWifi, behaviorWithAttachments, this.statuses);
|
||||||
|
options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
|
||||||
|
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
|
||||||
|
account_follow = (Button) findViewById(R.id.account_follow);
|
||||||
|
account_follow.setEnabled(false);
|
||||||
|
Bundle b = getIntent().getExtras();
|
||||||
|
if(b != null){
|
||||||
|
accountId = b.getString("accountId");
|
||||||
|
new RetrieveRelationshipAsyncTask(getApplicationContext(), accountId,ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
new RetrieveAccountAsyncTask(getApplicationContext(),accountId, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
|
||||||
|
if( accountId != null && accountId.equals(userId)){
|
||||||
|
account_follow.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Toast.makeText(this,R.string.toast_error_loading_account,Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
if( getSupportActionBar() != null)
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
|
|
||||||
|
tabLayout = (TabLayout) findViewById(R.id.account_tabLayout);
|
||||||
|
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.status)));
|
||||||
|
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.following)));
|
||||||
|
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.followers)));
|
||||||
|
|
||||||
|
mPager = (ViewPager) findViewById(R.id.account_viewpager);
|
||||||
|
PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
|
||||||
|
mPager.setAdapter(mPagerAdapter);
|
||||||
|
|
||||||
|
mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageSelected(int position) {
|
||||||
|
TabLayout.Tab tab = tabLayout.getTabAt(position);
|
||||||
|
if( tab != null)
|
||||||
|
tab.select();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrollStateChanged(int state) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onTabSelected(TabLayout.Tab tab) {
|
||||||
|
mPager.setCurrentItem(tab.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTabUnselected(TabLayout.Tab tab) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTabReselected(TabLayout.Tab tab) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//Follow button
|
||||||
|
account_follow.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if( doAction == action.FOLLOW){
|
||||||
|
account_follow.setEnabled(false);
|
||||||
|
new PostActionAsyncTask(getApplicationContext(), API.StatusAction.FOLLOW, accountId, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}else if( doAction == action.UNFOLLOW){
|
||||||
|
account_follow.setEnabled(false);
|
||||||
|
new PostActionAsyncTask(getApplicationContext(), API.StatusAction.UNFOLLOW, accountId, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}else if( doAction == action.UNBLOCK){
|
||||||
|
account_follow.setEnabled(false);
|
||||||
|
new PostActionAsyncTask(getApplicationContext(), API.StatusAction.UNBLOCK, accountId, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPostAction(int statusCode,API.StatusAction statusAction, String targetedId) {
|
||||||
|
Helper.manageMessageStatusCode(getApplicationContext(), statusCode, statusAction);
|
||||||
|
new RetrieveRelationshipAsyncTask(getApplicationContext(), accountId,ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveAccount(Account account) {
|
||||||
|
ImageView account_pp = (ImageView) findViewById(R.id.account_pp);
|
||||||
|
TextView account_dn = (TextView) findViewById(R.id.account_dn);
|
||||||
|
TextView account_un = (TextView) findViewById(R.id.account_un);
|
||||||
|
TextView account_ac = (TextView) findViewById(R.id.account_ac);
|
||||||
|
|
||||||
|
if( account != null){
|
||||||
|
setTitle(account.getAcct());
|
||||||
|
account_dn.setText(account.getDisplay_name());
|
||||||
|
account_un.setText(account.getUsername());
|
||||||
|
if( account.getAcct().equals(account.getUsername()))
|
||||||
|
account_ac.setVisibility(View.GONE);
|
||||||
|
else
|
||||||
|
account_ac.setText(account.getAcct());
|
||||||
|
tabLayout.getTabAt(0).setText(getString(R.string.status) + "\n" + String.valueOf(account.getStatuses_count()));
|
||||||
|
tabLayout.getTabAt(1).setText(getString(R.string.following) + "\n" + String.valueOf(account.getFollowing_count()));
|
||||||
|
tabLayout.getTabAt(2).setText(getString(R.string.followers) + "\n" + String.valueOf(account.getFollowers_count()));
|
||||||
|
imageLoader.displayImage(account.getAvatar(), account_pp, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveFeedsAccount(List<Status> statuses) {
|
||||||
|
if( statuses != null) {
|
||||||
|
for(Status tmpStatus: statuses){
|
||||||
|
this.statuses.add(tmpStatus);
|
||||||
|
}
|
||||||
|
statusListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveRelationship(Relationship relationship) {
|
||||||
|
if( relationship.isBlocking()){
|
||||||
|
account_follow.setText(R.string.action_unblock);
|
||||||
|
doAction = action.UNBLOCK;
|
||||||
|
}else if( relationship.isRequested()){
|
||||||
|
account_follow.setText(R.string.request_sent);
|
||||||
|
doAction = action.NOTHING;
|
||||||
|
}else if( relationship.isFollowing()){
|
||||||
|
account_follow.setText(R.string.action_unfollow);
|
||||||
|
doAction = action.UNFOLLOW;
|
||||||
|
}else if( !relationship.isFollowing()){
|
||||||
|
account_follow.setText(R.string.action_follow);
|
||||||
|
doAction = action.FOLLOW;
|
||||||
|
}else{
|
||||||
|
doAction = action.NOTHING;
|
||||||
|
}
|
||||||
|
if( doAction == action.NOTHING){
|
||||||
|
account_follow.setEnabled(false);
|
||||||
|
}else {
|
||||||
|
account_follow.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//The authenticated account is followed by the account
|
||||||
|
if( relationship.isFollowed_by()){
|
||||||
|
TextView account_followed_by = (TextView) findViewById(R.id.account_followed_by);
|
||||||
|
account_followed_by.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pager adapter for the 3 fragments
|
||||||
|
*/
|
||||||
|
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
|
||||||
|
ScreenSlidePagerAdapter(FragmentManager fm) {
|
||||||
|
super(fm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fragment getItem(int position) {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
switch (position){
|
||||||
|
case 0:
|
||||||
|
DisplayStatusFragment displayStatusFragment = new DisplayStatusFragment();
|
||||||
|
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.USER);
|
||||||
|
bundle.putString("targetedId", accountId);
|
||||||
|
displayStatusFragment.setArguments(bundle);
|
||||||
|
return displayStatusFragment;
|
||||||
|
case 1:
|
||||||
|
DisplayAccountsFragment displayAccountsFragment = new DisplayAccountsFragment();
|
||||||
|
bundle.putSerializable("type", RetrieveAccountsAsyncTask.Type.FOLLOWING);
|
||||||
|
bundle.putString("targetedId", accountId);
|
||||||
|
displayAccountsFragment.setArguments(bundle);
|
||||||
|
return displayAccountsFragment;
|
||||||
|
case 2:
|
||||||
|
displayAccountsFragment = new DisplayAccountsFragment();
|
||||||
|
bundle.putSerializable("type", RetrieveAccountsAsyncTask.Type.FOLLOWERS);
|
||||||
|
bundle.putString("targetedId", accountId);
|
||||||
|
displayAccountsFragment.setArguments(bundle);
|
||||||
|
return displayAccountsFragment;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return NUM_PAGES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.activities;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveContextAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Context;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Status;
|
||||||
|
import fr.gouv.etalab.mastodon.drawers.StatusListAdapter;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveContextInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 04/05/2017.
|
||||||
|
* Show conversation activity class
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ShowConversationActivity extends AppCompatActivity implements OnRetrieveFeedsInterface, OnRetrieveContextInterface {
|
||||||
|
|
||||||
|
|
||||||
|
private String statusId;
|
||||||
|
private Status initialStatus;
|
||||||
|
public static int position;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_show_conversation);
|
||||||
|
|
||||||
|
if( getSupportActionBar() != null)
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
Bundle b = getIntent().getExtras();
|
||||||
|
if(b != null)
|
||||||
|
statusId = b.getString("statusId", null);
|
||||||
|
if( statusId == null)
|
||||||
|
finish();
|
||||||
|
setTitle(R.string.conversation);
|
||||||
|
new RetrieveFeedsAsyncTask(getApplicationContext(), RetrieveFeedsAsyncTask.Type.ONESTATUS, statusId,null, ShowConversationActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveFeeds(List<Status> statuses) {
|
||||||
|
if( statuses != null && statuses.size() > 0 ){
|
||||||
|
initialStatus = statuses.get(0);
|
||||||
|
new RetrieveContextAsyncTask(getApplicationContext(), initialStatus.getId(), ShowConversationActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveFeeds(Context context) {
|
||||||
|
boolean isOnWifi = Helper.isOnWIFI(getApplicationContext());
|
||||||
|
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
|
||||||
|
int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
|
||||||
|
position = 0;
|
||||||
|
List<Status> statuses = new ArrayList<>();
|
||||||
|
if( context.getAncestors() != null && context.getAncestors().size() > 0){
|
||||||
|
for(Status status: context.getAncestors()){
|
||||||
|
statuses.add(status);
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statuses.add(initialStatus);
|
||||||
|
if( context.getDescendants() != null && context.getDescendants().size() > 0){
|
||||||
|
for(Status status: context.getDescendants()){
|
||||||
|
statuses.add(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RelativeLayout loader = (RelativeLayout) findViewById(R.id.loader);
|
||||||
|
ListView lv_status = (ListView) findViewById(R.id.lv_status);
|
||||||
|
StatusListAdapter statusListAdapter = new StatusListAdapter(ShowConversationActivity.this, RetrieveFeedsAsyncTask.Type.CONTEXT, isOnWifi, behaviorWithAttachments, statuses);
|
||||||
|
lv_status.setAdapter(statusListAdapter);
|
||||||
|
statusListAdapter.notifyDataSetChanged();
|
||||||
|
loader.setVisibility(View.GONE);
|
||||||
|
lv_status.setVisibility(View.VISIBLE);
|
||||||
|
lv_status.smoothScrollToPosition(position);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.activities;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 24/12/2016.
|
||||||
|
* splash screen activity
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SplashActivity extends AppCompatActivity {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
Intent intent = new Intent(this, MainActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,529 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.activities;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.design.widget.FloatingActionButton;
|
||||||
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import android.widget.VideoView;
|
||||||
|
|
||||||
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.PostActionAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveSearchAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.UploadActionAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Attachment;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Results;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Status;
|
||||||
|
import fr.gouv.etalab.mastodon.drawers.AccountsSearchAdapter;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAccountsInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAttachmentInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 01/05/2017.
|
||||||
|
* Toot activity class
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TootActivity extends AppCompatActivity implements OnRetrieveSearchInterface, OnRetrieveAttachmentInterface, OnPostActionInterface, OnRetrieveFeedsInterface {
|
||||||
|
|
||||||
|
|
||||||
|
private String inReplyTo = null;
|
||||||
|
private int charsInCw;
|
||||||
|
private int charsInToot;
|
||||||
|
private int maxChar;
|
||||||
|
private String visibility;
|
||||||
|
private final int PICK_IMAGE = 56556;
|
||||||
|
private RelativeLayout loading_picture;
|
||||||
|
private ImageButton toot_picture;
|
||||||
|
private ImageLoader imageLoader;
|
||||||
|
private DisplayImageOptions options;
|
||||||
|
private LinearLayout toot_picture_container;
|
||||||
|
private List<Attachment> attachments;
|
||||||
|
private ImageButton toot_visibility;
|
||||||
|
private Button toot_it;
|
||||||
|
private EditText toot_content, toot_cw_content;
|
||||||
|
private LinearLayout toot_reply_content_container;
|
||||||
|
private TextView toot_reply_content;
|
||||||
|
private RelativeLayout toot_show_accounts;
|
||||||
|
private ListView toot_lv_accounts;
|
||||||
|
private BroadcastReceiver search_validate;
|
||||||
|
|
||||||
|
private String pattern = "^.*(@([a-zA-Z0-9_]{2,}))$";
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_toot);
|
||||||
|
|
||||||
|
if( getSupportActionBar() != null)
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
|
|
||||||
|
Bundle b = getIntent().getExtras();
|
||||||
|
if(b != null)
|
||||||
|
inReplyTo = b.getString("inReplyTo", null);
|
||||||
|
if( inReplyTo != null) {
|
||||||
|
setTitle(R.string.toot_title_reply);
|
||||||
|
new RetrieveFeedsAsyncTask(getApplicationContext(), RetrieveFeedsAsyncTask.Type.ONESTATUS, inReplyTo,null, TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}else {
|
||||||
|
setTitle(R.string.toot_title);
|
||||||
|
}
|
||||||
|
attachments = new ArrayList<>();
|
||||||
|
charsInCw = 0;
|
||||||
|
charsInToot = 0;
|
||||||
|
maxChar = 500;
|
||||||
|
|
||||||
|
//Register LocalBroadcast to receive selected accounts after search
|
||||||
|
search_validate = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
String acct = intent.getStringExtra("acct");
|
||||||
|
if( acct != null){
|
||||||
|
acct = "@" + acct;
|
||||||
|
String content = toot_content.getText().toString();
|
||||||
|
String[] splitContent = content.split("@");
|
||||||
|
String newContent = "";
|
||||||
|
for(int i = 0 ; i < (splitContent.length -1) ; i++){
|
||||||
|
newContent += splitContent[i];
|
||||||
|
}
|
||||||
|
newContent += acct + " ";
|
||||||
|
toot_content.setText(newContent);
|
||||||
|
toot_content.setSelection(toot_content.getText().length());
|
||||||
|
}
|
||||||
|
toot_show_accounts.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
LocalBroadcastManager.getInstance(this).registerReceiver(search_validate, new IntentFilter(Helper.SEARCH_VALIDATE_ACCOUNT));
|
||||||
|
|
||||||
|
toot_it = (Button) findViewById(R.id.toot_it);
|
||||||
|
Button toot_cw = (Button) findViewById(R.id.toot_cw);
|
||||||
|
final TextView toot_space_left = (TextView) findViewById(R.id.toot_space_left);
|
||||||
|
toot_visibility = (ImageButton) findViewById(R.id.toot_visibility);
|
||||||
|
toot_picture = (ImageButton) findViewById(R.id.toot_picture);
|
||||||
|
loading_picture = (RelativeLayout) findViewById(R.id.loading_picture);
|
||||||
|
toot_picture_container = (LinearLayout) findViewById(R.id.toot_picture_container);
|
||||||
|
toot_content = (EditText) findViewById(R.id.toot_content);
|
||||||
|
toot_cw_content = (EditText) findViewById(R.id.toot_cw_content);
|
||||||
|
toot_reply_content = (TextView) findViewById(R.id.toot_reply_content);
|
||||||
|
toot_reply_content_container = (LinearLayout) findViewById(R.id.toot_reply_content_container);
|
||||||
|
toot_show_accounts = (RelativeLayout) findViewById(R.id.toot_show_accounts);
|
||||||
|
toot_lv_accounts = (ListView) findViewById(R.id.toot_lv_accounts);
|
||||||
|
FloatingActionButton toot_close_accounts = (FloatingActionButton) findViewById(R.id.toot_close_accounts);
|
||||||
|
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||||
|
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
|
||||||
|
Account account = new AccountDAO(getApplicationContext(),db).getAccountByID(userId);
|
||||||
|
boolean isAccountPrivate = account.isLocked();
|
||||||
|
|
||||||
|
|
||||||
|
FloatingActionButton ic_close = (FloatingActionButton) findViewById(R.id.toot_close_reply);
|
||||||
|
|
||||||
|
toot_close_accounts.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
toot_show_accounts.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ic_close.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
toot_reply_content_container.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(isAccountPrivate){
|
||||||
|
visibility = "private";
|
||||||
|
toot_visibility.setImageResource(R.drawable.ic_action_lock_closed);
|
||||||
|
}else {
|
||||||
|
visibility = "public";
|
||||||
|
toot_visibility.setImageResource(R.drawable.ic_action_globe);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
toot_space_left.setText(String.valueOf((maxChar - (charsInToot + charsInCw))));
|
||||||
|
toot_cw.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if(toot_cw_content.getVisibility() == View.GONE) {
|
||||||
|
toot_cw_content.setVisibility(View.VISIBLE);
|
||||||
|
toot_cw_content.requestFocus();
|
||||||
|
}else {
|
||||||
|
toot_cw_content.setVisibility(View.GONE);
|
||||||
|
toot_cw_content.setText("");
|
||||||
|
toot_content.requestFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
toot_visibility.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
tootVisibilityDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
imageLoader = ImageLoader.getInstance();
|
||||||
|
options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
|
||||||
|
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
|
||||||
|
|
||||||
|
toot_it.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
toot_it.setEnabled(false);
|
||||||
|
if(toot_content.getText().toString().trim().length() == 0){
|
||||||
|
Toast.makeText(getApplicationContext(),R.string.toot_error_no_content, Toast.LENGTH_LONG).show();
|
||||||
|
toot_it.setEnabled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Status toot = new Status();
|
||||||
|
toot.setMedia_attachments(attachments);
|
||||||
|
if( toot_cw_content.getText().toString().trim().length() > 0)
|
||||||
|
toot.setSpoiler_text(toot_cw_content.getText().toString().trim());
|
||||||
|
toot.setVisibility(visibility);
|
||||||
|
toot.setContent(toot_content.getText().toString().trim());
|
||||||
|
if( inReplyTo != null)
|
||||||
|
toot.setIn_reply_to_id(inReplyTo);
|
||||||
|
new PostActionAsyncTask(getApplicationContext(), API.StatusAction.CREATESTATUS, null, toot, null, TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
toot_picture.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
|
getIntent.setType("image/*");
|
||||||
|
|
||||||
|
Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||||
|
pickIntent.setType("image/*");
|
||||||
|
|
||||||
|
Intent chooserIntent = Intent.createChooser(getIntent, getString(R.string.toot_select_image));
|
||||||
|
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});
|
||||||
|
startActivityForResult(chooserIntent, PICK_IMAGE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
toot_content.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
|
||||||
|
Pattern sPattern = Pattern.compile(pattern);
|
||||||
|
Matcher m = sPattern.matcher(s.toString());
|
||||||
|
if(m.matches()) {
|
||||||
|
String search = m.group(2);
|
||||||
|
new RetrieveSearchAsyncTask(getApplicationContext(),search,TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}else{
|
||||||
|
toot_show_accounts.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
if( s.length() + charsInCw > maxChar){
|
||||||
|
String content = s.toString().substring(0,(maxChar - charsInCw));
|
||||||
|
toot_content.setText(content);
|
||||||
|
charsInToot = content.length();
|
||||||
|
toot_content.setSelection(toot_content.getText().length());
|
||||||
|
Toast.makeText(getApplicationContext(),R.string.toot_no_space,Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
int totalChar = toot_cw_content.length() + toot_content.length();
|
||||||
|
toot_space_left.setText(String.valueOf((maxChar - totalChar)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
toot_cw_content.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
if( s.length() + charsInToot > maxChar){
|
||||||
|
String content = s.toString().substring(0,(maxChar - charsInToot));
|
||||||
|
toot_cw_content.setText(content);
|
||||||
|
toot_cw_content.setSelection(toot_cw_content.getText().length());
|
||||||
|
Toast.makeText(getApplicationContext(),R.string.toot_no_space,Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
int totalChar = toot_cw_content.length() + toot_content.length();
|
||||||
|
toot_space_left.setText(String.valueOf((maxChar - totalChar)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK) {
|
||||||
|
if (data == null) {
|
||||||
|
Toast.makeText(getApplicationContext(),R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
|
||||||
|
InputStream inputStream = getContentResolver().openInputStream(data.getData());
|
||||||
|
loading_picture.setVisibility(View.VISIBLE);
|
||||||
|
toot_picture.setEnabled(false);
|
||||||
|
new UploadActionAsyncTask(getApplicationContext(),inputStream,TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Toast.makeText(getApplicationContext(),R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
|
||||||
|
loading_picture.setVisibility(View.GONE);
|
||||||
|
toot_picture.setEnabled(true);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy(){
|
||||||
|
super.onDestroy();
|
||||||
|
LocalBroadcastManager.getInstance(this).unregisterReceiver(search_validate);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onRetrieveAttachment(final Attachment attachment) {
|
||||||
|
loading_picture.setVisibility(View.GONE);
|
||||||
|
toot_picture_container.setVisibility(View.VISIBLE);
|
||||||
|
if( attachment != null ){
|
||||||
|
String url = attachment.getPreview_url();
|
||||||
|
if( url == null || url.trim().equals(""))
|
||||||
|
url = attachment.getUrl();
|
||||||
|
|
||||||
|
final ImageView imageView = new ImageView(getApplicationContext());
|
||||||
|
imageView.setId(Integer.parseInt(attachment.getId()));
|
||||||
|
LinearLayout.LayoutParams imParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||||
|
imParams.setMargins(20, 5, 20, 5);
|
||||||
|
imageLoader.displayImage(url, imageView, options);
|
||||||
|
imageView.setAdjustViewBounds(true);
|
||||||
|
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
|
||||||
|
toot_picture_container.addView(imageView, imParams);
|
||||||
|
imageView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
showRemove(imageView.getId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
attachments.add(attachment);
|
||||||
|
if( attachments.size() < 4)
|
||||||
|
toot_picture.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a media
|
||||||
|
* @param viewId String
|
||||||
|
*/
|
||||||
|
private void showRemove(final int viewId){
|
||||||
|
|
||||||
|
AlertDialog.Builder dialog = new AlertDialog.Builder(TootActivity.this);
|
||||||
|
|
||||||
|
dialog.setMessage(R.string.toot_delete_media);
|
||||||
|
dialog.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog,int which) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog,int which) {
|
||||||
|
List<Attachment> tmp_attachment = new ArrayList<>();
|
||||||
|
tmp_attachment.addAll(attachments);
|
||||||
|
attachments.removeAll(tmp_attachment);
|
||||||
|
tmp_attachment.clear();
|
||||||
|
View namebar = findViewById(viewId);
|
||||||
|
((ViewGroup) namebar.getParent()).removeView(namebar);
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.show();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void tootVisibilityDialog(){
|
||||||
|
|
||||||
|
|
||||||
|
AlertDialog.Builder dialog = new AlertDialog.Builder(TootActivity.this);
|
||||||
|
dialog.setTitle(R.string.toot_visibility_tilte);
|
||||||
|
final String[] stringArray = getResources().getStringArray(R.array.toot_visibility);
|
||||||
|
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(TootActivity.this, android.R.layout.simple_list_item_1, stringArray);
|
||||||
|
dialog.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int position) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int position) {
|
||||||
|
switch (position){
|
||||||
|
case 0:
|
||||||
|
visibility = "public";
|
||||||
|
toot_visibility.setImageResource(R.drawable.ic_action_globe);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
visibility = "unlisted";
|
||||||
|
toot_visibility.setImageResource(R.drawable.ic_action_lock_open);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
visibility = "private";
|
||||||
|
toot_visibility.setImageResource(R.drawable.ic_action_lock_closed);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
visibility = "direct";
|
||||||
|
toot_visibility.setImageResource(R.drawable.ic_local_post_office);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPostAction(int statusCode, API.StatusAction statusAction, String userId) {
|
||||||
|
if( statusCode == 200){
|
||||||
|
//Clear the toot
|
||||||
|
toot_content.setText("");
|
||||||
|
toot_cw_content.setText("");
|
||||||
|
if( attachments != null) {
|
||||||
|
for (Attachment attachment : attachments) {
|
||||||
|
View namebar = findViewById(Integer.parseInt(attachment.getId()));
|
||||||
|
if (namebar != null && namebar.getParent() != null)
|
||||||
|
((ViewGroup) namebar.getParent()).removeView(namebar);
|
||||||
|
}
|
||||||
|
List<Attachment> tmp_attachment = new ArrayList<>();
|
||||||
|
tmp_attachment.addAll(attachments);
|
||||||
|
attachments.removeAll(tmp_attachment);
|
||||||
|
tmp_attachment.clear();
|
||||||
|
}
|
||||||
|
Toast.makeText(TootActivity.this,R.string.toot_sent, Toast.LENGTH_LONG).show();
|
||||||
|
}else {
|
||||||
|
Toast.makeText(TootActivity.this,R.string.toast_error, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
toot_it.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveFeeds(List<Status> statuses) {
|
||||||
|
if( statuses != null && statuses.size() > 0 ){
|
||||||
|
toot_reply_content_container.setVisibility(View.VISIBLE);
|
||||||
|
String content = statuses.get(0).getContent();
|
||||||
|
if(statuses.get(0).isReblogged())
|
||||||
|
content = statuses.get(0).getReblog().getContent();
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||||
|
toot_reply_content.setText(Html.fromHtml(content, Html.FROM_HTML_MODE_COMPACT));
|
||||||
|
else
|
||||||
|
//noinspection deprecation
|
||||||
|
toot_reply_content.setText(Html.fromHtml(content));
|
||||||
|
switch (statuses.get(0).getVisibility()){
|
||||||
|
case "public":
|
||||||
|
visibility = "public";
|
||||||
|
toot_visibility.setImageResource(R.drawable.ic_action_globe);
|
||||||
|
break;
|
||||||
|
case "unlisted":
|
||||||
|
visibility = "unlisted";
|
||||||
|
toot_visibility.setImageResource(R.drawable.ic_action_lock_open);
|
||||||
|
break;
|
||||||
|
case "private":
|
||||||
|
visibility = "private";
|
||||||
|
toot_visibility.setImageResource(R.drawable.ic_action_lock_closed);
|
||||||
|
break;
|
||||||
|
case "direct":
|
||||||
|
visibility = "direct";
|
||||||
|
toot_visibility.setImageResource(R.drawable.ic_local_post_office);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveSearch(Results results) {
|
||||||
|
if( results != null && results.getAccounts() != null && results.getAccounts().size() > 0){
|
||||||
|
AccountsSearchAdapter accountsListAdapter = new AccountsSearchAdapter(TootActivity.this, results.getAccounts());
|
||||||
|
toot_lv_accounts.setAdapter(accountsListAdapter);
|
||||||
|
accountsListAdapter.notifyDataSetChanged();
|
||||||
|
toot_show_accounts.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
package fr.gouv.etalab.mastodon.activities;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.webkit.CookieManager;
|
||||||
|
import android.webkit.CookieSyncManager;
|
||||||
|
import android.webkit.WebChromeClient;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.webkit.WebViewClient;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import com.loopj.android.http.AsyncHttpResponseHandler;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import cz.msebera.android.httpclient.Header;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.UpdateAccountInfoAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.client.OauthClient;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 24/04/2017.
|
||||||
|
* Webview to connect accounts
|
||||||
|
*/
|
||||||
|
public class WebviewActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
|
||||||
|
private Activity activity;
|
||||||
|
private WebView webView;
|
||||||
|
private Context context;
|
||||||
|
private AlertDialog alert;
|
||||||
|
private String clientId, clientSecret;
|
||||||
|
|
||||||
|
public void onCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_webview);
|
||||||
|
this.activity = this;
|
||||||
|
this.context = this;
|
||||||
|
this.context = this.getApplicationContext();
|
||||||
|
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
clientId = sharedpreferences.getString(Helper.CLIENT_ID, null);
|
||||||
|
clientSecret = sharedpreferences.getString(Helper.CLIENT_SECRET, null);
|
||||||
|
|
||||||
|
webView = (WebView) findViewById(R.id.webviewConnect);
|
||||||
|
clearCookies(getApplicationContext());
|
||||||
|
final ProgressBar pbar = (ProgressBar) findViewById(R.id.progress_bar);
|
||||||
|
|
||||||
|
webView.setWebChromeClient(new WebChromeClient() {
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(WebView view, int progress) {
|
||||||
|
if (progress < 100 && pbar.getVisibility() == ProgressBar.GONE) {
|
||||||
|
pbar.setVisibility(ProgressBar.VISIBLE);
|
||||||
|
}
|
||||||
|
pbar.setProgress(progress);
|
||||||
|
if (progress == 100) {
|
||||||
|
pbar.setVisibility(ProgressBar.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
webView.setWebViewClient(new WebViewClient() {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Override
|
||||||
|
public boolean shouldOverrideUrlLoading(WebView view, String url){
|
||||||
|
super.shouldOverrideUrlLoading(view,url);
|
||||||
|
if( url.contains(Helper.REDIRECT_CONTENT)){
|
||||||
|
String val[] = url.split("code=");
|
||||||
|
String code = val[1];
|
||||||
|
|
||||||
|
String action = "/oauth/token";
|
||||||
|
HashMap<String,String> parameters = new HashMap<>();
|
||||||
|
parameters.put(Helper.CLIENT_ID, clientId);
|
||||||
|
parameters.put(Helper.CLIENT_SECRET, clientSecret);
|
||||||
|
parameters.put(Helper.REDIRECT_URI,"https://" + Helper.INSTANCE + Helper.REDIRECT_CONTENT);
|
||||||
|
parameters.put("grant_type", "authorization_code");
|
||||||
|
parameters.put("code",code);
|
||||||
|
new OauthClient().post(action, parameters, new AsyncHttpResponseHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
|
||||||
|
String response = new String(responseBody);
|
||||||
|
JSONObject resobj;
|
||||||
|
try {
|
||||||
|
resobj = new JSONObject(response);
|
||||||
|
String token = resobj.get("access_token").toString();
|
||||||
|
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, token);
|
||||||
|
editor.apply();
|
||||||
|
//Update the account with the token;
|
||||||
|
new UpdateAccountInfoAsyncTask(WebviewActivity.this, true, token).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
|
||||||
|
error.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
webView.loadUrl(redirectUserToAuthorizeAndLogin());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
if (webView != null && webView.canGoBack()) {
|
||||||
|
webView.goBack();
|
||||||
|
} else {
|
||||||
|
super.onBackPressed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String redirectUserToAuthorizeAndLogin() {
|
||||||
|
|
||||||
|
String queryString = Helper.CLIENT_ID + "="+ clientId;
|
||||||
|
queryString += "&" + Helper.REDIRECT_URI + "="+ Uri.encode("https://" + Helper.INSTANCE + "/redirect_mastodon_api");
|
||||||
|
queryString += "&" + Helper.RESPONSE_TYPE +"=code";
|
||||||
|
queryString += "&" + Helper.SCOPE +"=" + Helper.OAUTH_SCOPES;
|
||||||
|
/*try {
|
||||||
|
queryString = URLEncoder.encode(queryString, "utf-8");
|
||||||
|
} catch (UnsupportedEncodingException ignored) {}*/
|
||||||
|
return "https://" + Helper.INSTANCE + Helper.EP_AUTHORIZE + "?" + queryString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getOauthRedirectUri() {
|
||||||
|
return Helper.OAUTH_SCHEME + "://" + Helper.OAUTH_REDIRECT_HOST + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (alert != null) {
|
||||||
|
alert.dismiss();
|
||||||
|
alert = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static void clearCookies(Context context)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||||
|
CookieManager.getInstance().removeAllCookies(null);
|
||||||
|
CookieManager.getInstance().flush();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
CookieSyncManager cookieSyncMngr=CookieSyncManager.createInstance(context);
|
||||||
|
cookieSyncMngr.startSync();
|
||||||
|
CookieManager cookieManager=CookieManager.getInstance();
|
||||||
|
cookieManager.removeAllCookie();
|
||||||
|
cookieManager.removeSessionCookie();
|
||||||
|
cookieSyncMngr.stopSync();
|
||||||
|
cookieSyncMngr.sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 29/04/2017.
|
||||||
|
* Makes actions for post calls
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PostActionAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private OnPostActionInterface listener;
|
||||||
|
private int statusCode;
|
||||||
|
private API.StatusAction statusAction;
|
||||||
|
private String statusId;
|
||||||
|
private String comment;
|
||||||
|
private Account account;
|
||||||
|
private fr.gouv.etalab.mastodon.client.Entities.Status status;
|
||||||
|
|
||||||
|
public PostActionAsyncTask(Context context, API.StatusAction statusAction, String statusId, OnPostActionInterface onPostActionInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.listener = onPostActionInterface;
|
||||||
|
this.statusAction = statusAction;
|
||||||
|
this.statusId = statusId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostActionAsyncTask(Context context, API.StatusAction statusAction, String statusId, fr.gouv.etalab.mastodon.client.Entities.Status status, String comment, OnPostActionInterface onPostActionInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.listener = onPostActionInterface;
|
||||||
|
this.statusAction = statusAction;
|
||||||
|
this.statusId = statusId;
|
||||||
|
this.comment = comment;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
|
||||||
|
if(statusAction == API.StatusAction.REPORT)
|
||||||
|
statusCode = new API(context).reportAction(status, comment);
|
||||||
|
else if(statusAction == API.StatusAction.CREATESTATUS)
|
||||||
|
statusCode = new API(context).statusAction(status);
|
||||||
|
else
|
||||||
|
statusCode = new API(context).postAction(statusAction, statusId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
listener.onPostAction(statusCode, statusAction, statusId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAccountInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 27/04/2017.
|
||||||
|
* Retrieves accounts on the instance
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class RetrieveAccountAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private String targetedId;
|
||||||
|
private Account account;
|
||||||
|
private OnRetrieveAccountInterface listener;
|
||||||
|
|
||||||
|
|
||||||
|
public RetrieveAccountAsyncTask(Context context, String targetedId, OnRetrieveAccountInterface onRetrieveAccountInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.targetedId = targetedId;
|
||||||
|
this.listener = onRetrieveAccountInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
|
||||||
|
account = new API(context).getAccount(targetedId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
listener.onRetrieveAccount(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAccountsInterface;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 27/04/2017.
|
||||||
|
* Retrieves accounts on the instance
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class RetrieveAccountsAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private Type action;
|
||||||
|
private List<Account> accounts;
|
||||||
|
private String max_id;
|
||||||
|
private OnRetrieveAccountsInterface listener;
|
||||||
|
private String targetedId;
|
||||||
|
|
||||||
|
public enum Type{
|
||||||
|
BLOCKED,
|
||||||
|
MUTED,
|
||||||
|
FOLLOWING,
|
||||||
|
FOLLOWERS
|
||||||
|
}
|
||||||
|
|
||||||
|
public RetrieveAccountsAsyncTask(Context context, Type action, String targetedId, String max_id, OnRetrieveAccountsInterface onRetrieveAccountsInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.action = action;
|
||||||
|
this.max_id = max_id;
|
||||||
|
this.listener = onRetrieveAccountsInterface;
|
||||||
|
this.targetedId = targetedId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RetrieveAccountsAsyncTask(Context context, Type action, String max_id, OnRetrieveAccountsInterface onRetrieveAccountsInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.action = action;
|
||||||
|
this.max_id = max_id;
|
||||||
|
this.listener = onRetrieveAccountsInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
|
||||||
|
switch (action){
|
||||||
|
case BLOCKED:
|
||||||
|
accounts = new API(context).getBlocks(max_id);
|
||||||
|
break;
|
||||||
|
case MUTED:
|
||||||
|
accounts = new API(context).getMuted(max_id);
|
||||||
|
break;
|
||||||
|
case FOLLOWING:
|
||||||
|
accounts = new API(context).getFollowing(targetedId, max_id);
|
||||||
|
break;
|
||||||
|
case FOLLOWERS:
|
||||||
|
accounts = new API(context).getFollowers(targetedId, max_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
listener.onRetrieveAccounts(accounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveContextInterface;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
* Retrieves context for a status
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class RetrieveContextAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private String statusId;
|
||||||
|
private fr.gouv.etalab.mastodon.client.Entities.Context statusContext;
|
||||||
|
private OnRetrieveContextInterface listener;
|
||||||
|
|
||||||
|
public RetrieveContextAsyncTask(Context context, String statusId, OnRetrieveContextInterface onRetrieveContextInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.statusId = statusId;
|
||||||
|
this.listener = onRetrieveContextInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
statusContext = new API(context).getStatusContext(statusId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
listener.onRetrieveFeeds(statusContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsAccountInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 01/05/2017.
|
||||||
|
* Retrieves toots for an account
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class RetrieveFeedsAccountAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private String accountId;
|
||||||
|
private List<fr.gouv.etalab.mastodon.client.Entities.Status> statuses;
|
||||||
|
private OnRetrieveFeedsAccountInterface listener;
|
||||||
|
|
||||||
|
|
||||||
|
public RetrieveFeedsAccountAsyncTask(Context context, String accountId, OnRetrieveFeedsAccountInterface onRetrieveFeedsAccountInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.listener = onRetrieveFeedsAccountInterface;
|
||||||
|
this.accountId = accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
|
||||||
|
statuses = new API(context).getStatus(accountId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
listener.onRetrieveFeedsAccount(statuses);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
* Retrieves toots on the instance
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private Type action;
|
||||||
|
private List<fr.gouv.etalab.mastodon.client.Entities.Status> statuses;
|
||||||
|
private String max_id;
|
||||||
|
private OnRetrieveFeedsInterface listener;
|
||||||
|
private String targetedID;
|
||||||
|
private fr.gouv.etalab.mastodon.client.Entities.Status status;
|
||||||
|
private String tag;
|
||||||
|
|
||||||
|
public enum Type{
|
||||||
|
HOME,
|
||||||
|
LOCAL,
|
||||||
|
PUBLIC,
|
||||||
|
HASHTAG,
|
||||||
|
USER,
|
||||||
|
FAVOURITES,
|
||||||
|
ONESTATUS,
|
||||||
|
CONTEXT,
|
||||||
|
TAG
|
||||||
|
}
|
||||||
|
|
||||||
|
public RetrieveFeedsAsyncTask(Context context, Type action, String max_id, OnRetrieveFeedsInterface onRetrieveFeedsInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.action = action;
|
||||||
|
this.max_id = max_id;
|
||||||
|
this.listener = onRetrieveFeedsInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RetrieveFeedsAsyncTask(Context context, Type action, String targetedID, String max_id, OnRetrieveFeedsInterface onRetrieveFeedsInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.action = action;
|
||||||
|
this.max_id = max_id;
|
||||||
|
this.listener = onRetrieveFeedsInterface;
|
||||||
|
this.targetedID = targetedID;
|
||||||
|
}
|
||||||
|
public RetrieveFeedsAsyncTask(Context context, Type action, String tag, String targetedID, String max_id, OnRetrieveFeedsInterface onRetrieveFeedsInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.action = action;
|
||||||
|
this.max_id = max_id;
|
||||||
|
this.listener = onRetrieveFeedsInterface;
|
||||||
|
this.targetedID = targetedID;
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
|
||||||
|
switch (action){
|
||||||
|
case HOME:
|
||||||
|
statuses = new API(context).getHomeTimeline(max_id);
|
||||||
|
break;
|
||||||
|
case LOCAL:
|
||||||
|
statuses = new API(context).getPublicTimeline(true, max_id);
|
||||||
|
break;
|
||||||
|
case PUBLIC:
|
||||||
|
statuses = new API(context).getPublicTimeline(false, max_id);
|
||||||
|
break;
|
||||||
|
case FAVOURITES:
|
||||||
|
statuses = new API(context).getFavourites(max_id);
|
||||||
|
break;
|
||||||
|
case USER:
|
||||||
|
statuses = new API(context).getStatus(targetedID, max_id);
|
||||||
|
break;
|
||||||
|
case ONESTATUS:
|
||||||
|
statuses = new API(context).getStatusbyId(targetedID);
|
||||||
|
break;
|
||||||
|
case TAG:
|
||||||
|
statuses = new API(context).getPublicTimelineTag(tag, true, max_id);
|
||||||
|
break;
|
||||||
|
case HASHTAG:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
listener.onRetrieveFeeds(statuses);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveNotificationsInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 28/04/2017.
|
||||||
|
* Retrieves notifications on the instance
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class RetrieveNotificationsAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private List<Notification> notifications;
|
||||||
|
private String max_id;
|
||||||
|
private String acct;
|
||||||
|
private OnRetrieveNotificationsInterface listener;
|
||||||
|
|
||||||
|
|
||||||
|
public RetrieveNotificationsAsyncTask(Context context, String max_id, String acct, OnRetrieveNotificationsInterface onRetrieveNotificationsInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.max_id = max_id;
|
||||||
|
this.listener = onRetrieveNotificationsInterface;
|
||||||
|
this.acct = acct;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
if( acct == null)
|
||||||
|
notifications = new API(context).getNotifications(max_id);
|
||||||
|
else
|
||||||
|
notifications = new API(context).getNotificationsSince(max_id);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
listener.onRetrieveNotifications(notifications, acct);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Relationship;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveRelationshipInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 01/05/2017.
|
||||||
|
* Retrieves relationship between the authenticated user and another account
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class RetrieveRelationshipAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private String accountId;
|
||||||
|
private Relationship relationship;
|
||||||
|
private OnRetrieveRelationshipInterface listener;
|
||||||
|
|
||||||
|
|
||||||
|
public RetrieveRelationshipAsyncTask(Context context, String accountId, OnRetrieveRelationshipInterface onRetrieveRelationshipInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.listener = onRetrieveRelationshipInterface;
|
||||||
|
this.accountId = accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
|
||||||
|
relationship = new API(context).getRelationship(accountId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
listener.onRetrieveRelationship(relationship);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Results;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchInterface;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 05/05/2017.
|
||||||
|
* Retrieves accounts from search (ie: starting with @ when writing a toot)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class RetrieveSearchAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private String query;
|
||||||
|
private Results results;
|
||||||
|
private OnRetrieveSearchInterface listener;
|
||||||
|
|
||||||
|
|
||||||
|
public RetrieveSearchAsyncTask(Context context, String query, OnRetrieveSearchInterface onRetrieveSearchInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.query = query;
|
||||||
|
this.listener = onRetrieveSearchInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
|
||||||
|
results = new API(context).search(query);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
listener.onRetrieveSearch(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.activities.MainActivity;
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnUpdateAccountInfoInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
* Manage the synchronization with the account and update the db
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class UpdateAccountInfoAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private String token;
|
||||||
|
private boolean fromWebview;
|
||||||
|
private boolean error;
|
||||||
|
private OnUpdateAccountInfoInterface listener;
|
||||||
|
|
||||||
|
public UpdateAccountInfoAsyncTask(Context context, String token, OnUpdateAccountInfoInterface onUpdateAccountInfoInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.token = token;
|
||||||
|
this.fromWebview = false;
|
||||||
|
this.error = false;
|
||||||
|
this.listener = onUpdateAccountInfoInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdateAccountInfoAsyncTask(Context context, boolean fromWebview, String token){
|
||||||
|
this.context = context;
|
||||||
|
this.token = token;
|
||||||
|
this.fromWebview = fromWebview;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
Account account = new API(context).verifyCredentials();
|
||||||
|
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
if( token == null) {
|
||||||
|
token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
|
||||||
|
}
|
||||||
|
account.setToken(token);
|
||||||
|
//TODO: remove this static value to allow other instances
|
||||||
|
account.setInstance(Helper.INSTANCE);
|
||||||
|
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||||
|
boolean userExists = new AccountDAO(context, db).userExist(account);
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putString(Helper.PREF_KEY_ID, account.getId());
|
||||||
|
editor.apply();
|
||||||
|
if( userExists)
|
||||||
|
new AccountDAO(context, db).updateAccount(account);
|
||||||
|
else {
|
||||||
|
if( account.getUsername() != null && account.getCreated_at() != null)
|
||||||
|
new AccountDAO(context, db).insertAccount(account);
|
||||||
|
else //Here the user credential in db doesn't match the remote one (it will be disconnected)
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
|
||||||
|
if( fromWebview){
|
||||||
|
Intent mainActivity = new Intent(context, MainActivity.class);
|
||||||
|
mainActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
context.startActivity(mainActivity);
|
||||||
|
((Activity) context).finish();
|
||||||
|
}else{
|
||||||
|
listener.onUpdateAccountInfo(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Attachment;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAttachmentInterface;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 01/05/2017.
|
||||||
|
* Proceeds to file upload
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class UploadActionAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private OnRetrieveAttachmentInterface listener;
|
||||||
|
private Attachment attachment;
|
||||||
|
private InputStream inputStream;
|
||||||
|
private fr.gouv.etalab.mastodon.client.Entities.Status status;
|
||||||
|
|
||||||
|
public UploadActionAsyncTask(Context context, InputStream inputStream, OnRetrieveAttachmentInterface onRetrieveAttachmentInterface){
|
||||||
|
this.context = context;
|
||||||
|
this.listener = onRetrieveAttachmentInterface;
|
||||||
|
this.inputStream = inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
|
||||||
|
attachment = new API(context).uploadMedia(inputStream);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
listener.onRetrieveAttachment(attachment);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,178 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Account {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String username;
|
||||||
|
private String acct;
|
||||||
|
private String display_name;
|
||||||
|
private boolean locked;
|
||||||
|
private Date created_at;
|
||||||
|
private int followers_count;
|
||||||
|
private int following_count;
|
||||||
|
private int statuses_count;
|
||||||
|
private String note;
|
||||||
|
private String url;
|
||||||
|
private String avatar;
|
||||||
|
private String avatar_static;
|
||||||
|
private String header;
|
||||||
|
private String header_static;
|
||||||
|
private String token;
|
||||||
|
private String instance;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAcct() {
|
||||||
|
return acct;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAcct(String acct) {
|
||||||
|
this.acct = acct;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplay_name() {
|
||||||
|
return display_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDisplay_name(String display_name) {
|
||||||
|
this.display_name = display_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLocked() {
|
||||||
|
return locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocked(boolean locked) {
|
||||||
|
this.locked = locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreated_at() {
|
||||||
|
return created_at;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreated_at(Date created_at) {
|
||||||
|
this.created_at = created_at;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFollowers_count() {
|
||||||
|
return followers_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFollowers_count(int followers_count) {
|
||||||
|
this.followers_count = followers_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFollowing_count() {
|
||||||
|
return following_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFollowing_count(int following_count) {
|
||||||
|
this.following_count = following_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatuses_count() {
|
||||||
|
return statuses_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatuses_count(int statuses_count) {
|
||||||
|
this.statuses_count = statuses_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNote() {
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNote(String note) {
|
||||||
|
this.note = note;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAvatar() {
|
||||||
|
return avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatar(String avatar) {
|
||||||
|
this.avatar = avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAvatar_static() {
|
||||||
|
return avatar_static;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatar_static(String avatar_static) {
|
||||||
|
this.avatar_static = avatar_static;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(String header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHeader_static() {
|
||||||
|
return header_static;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader_static(String header_static) {
|
||||||
|
this.header_static = header_static;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInstance(String instance) {
|
||||||
|
this.instance = instance;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public String name;
|
||||||
|
public String website;
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Attachment {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String type;
|
||||||
|
private String url;
|
||||||
|
private String remote_url;
|
||||||
|
private String preview_url;
|
||||||
|
private String text_url;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemote_url() {
|
||||||
|
return remote_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemote_url(String remote_url) {
|
||||||
|
this.remote_url = remote_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPreview_url() {
|
||||||
|
return preview_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPreview_url(String preview_url) {
|
||||||
|
this.preview_url = preview_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText_url() {
|
||||||
|
return text_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText_url(String text_url) {
|
||||||
|
this.text_url = text_url;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Card {
|
||||||
|
|
||||||
|
public String url;
|
||||||
|
public String title;
|
||||||
|
public String description;
|
||||||
|
public String image;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
* Manage status Context
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Context {
|
||||||
|
|
||||||
|
private List<Status> ancestors;
|
||||||
|
private List<Status> descendants;
|
||||||
|
|
||||||
|
public List<Status> getAncestors() {
|
||||||
|
return ancestors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAncestors(List<Status> ancestors) {
|
||||||
|
this.ancestors = ancestors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Status> getDescendants() {
|
||||||
|
return descendants;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescendants(List<Status> descendants) {
|
||||||
|
this.descendants = descendants;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Error {
|
||||||
|
|
||||||
|
private String error;
|
||||||
|
|
||||||
|
public String getError() {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setError(String error) {
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Mention {
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
private String username;
|
||||||
|
private String acct;
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAcct() {
|
||||||
|
return acct;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAcct(String acct) {
|
||||||
|
this.acct = acct;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Notification {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String type;
|
||||||
|
private Date created_at;
|
||||||
|
private Account account;
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreated_at() {
|
||||||
|
return created_at;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreated_at(Date created_at) {
|
||||||
|
this.created_at = created_at;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account getAccount() {
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccount(Account account) {
|
||||||
|
this.account = account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
* Manage relationship between the authenticated account and another account
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Relationship {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private boolean following;
|
||||||
|
private boolean followed_by;
|
||||||
|
private boolean blocking;
|
||||||
|
private boolean muting;
|
||||||
|
private boolean requested;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFollowing() {
|
||||||
|
return following;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFollowing(boolean following) {
|
||||||
|
this.following = following;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFollowed_by() {
|
||||||
|
return followed_by;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFollowed_by(boolean followed_by) {
|
||||||
|
this.followed_by = followed_by;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBlocking() {
|
||||||
|
return blocking;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBlocking(boolean blocking) {
|
||||||
|
this.blocking = blocking;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMuting() {
|
||||||
|
return muting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMuting(boolean muting) {
|
||||||
|
this.muting = muting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRequested() {
|
||||||
|
return requested;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequested(boolean requested) {
|
||||||
|
this.requested = requested;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 05/05/2017.
|
||||||
|
* Manage Results for search
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Results {
|
||||||
|
|
||||||
|
private List<Account> accounts;
|
||||||
|
private List<Status> statuses;
|
||||||
|
private List<String> hashtags;
|
||||||
|
|
||||||
|
public List<Account> getAccounts() {
|
||||||
|
return accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccounts(List<Account> accounts) {
|
||||||
|
this.accounts = accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Status> getStatuses() {
|
||||||
|
return statuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatuses(List<Status> statuses) {
|
||||||
|
this.statuses = statuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getHashtags() {
|
||||||
|
return hashtags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashtags(List<String> hashtags) {
|
||||||
|
this.hashtags = hashtags;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,220 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Status {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String uri;
|
||||||
|
private String url;
|
||||||
|
private Account account;
|
||||||
|
private String in_reply_to_id;
|
||||||
|
private String in_reply_to_account_id;
|
||||||
|
private Status reblog;
|
||||||
|
private String content;
|
||||||
|
private Date created_at;
|
||||||
|
private int reblogs_count;
|
||||||
|
private int favourites_count;
|
||||||
|
private boolean reblogged;
|
||||||
|
private boolean favourited;
|
||||||
|
private boolean sensitive;
|
||||||
|
private String spoiler_text;
|
||||||
|
private String visibility;
|
||||||
|
private boolean attachmentShown = false;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUri(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account getAccount() {
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccount(Account account) {
|
||||||
|
this.account = account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIn_reply_to_id() {
|
||||||
|
return in_reply_to_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIn_reply_to_id(String in_reply_to_id) {
|
||||||
|
this.in_reply_to_id = in_reply_to_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIn_reply_to_account_id() {
|
||||||
|
return in_reply_to_account_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIn_reply_to_account_id(String in_reply_to_account_id) {
|
||||||
|
this.in_reply_to_account_id = in_reply_to_account_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status getReblog() {
|
||||||
|
return reblog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReblog(Status reblog) {
|
||||||
|
this.reblog = reblog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getReblogs_count() {
|
||||||
|
return reblogs_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReblogs_count(int reblogs_count) {
|
||||||
|
this.reblogs_count = reblogs_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreated_at() {
|
||||||
|
return created_at;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreated_at(Date created_at) {
|
||||||
|
this.created_at = created_at;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFavourites_count() {
|
||||||
|
return favourites_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFavourites_count(int favourites_count) {
|
||||||
|
this.favourites_count = favourites_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReblogged() {
|
||||||
|
return reblogged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReblogged(boolean reblogged) {
|
||||||
|
this.reblogged = reblogged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFavourited() {
|
||||||
|
return favourited;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFavourited(boolean favourited) {
|
||||||
|
this.favourited = favourited;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSensitive() {
|
||||||
|
return sensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSensitive(boolean sensitive) {
|
||||||
|
this.sensitive = sensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSpoiler_text() {
|
||||||
|
return spoiler_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpoiler_text(String spoiler_text) {
|
||||||
|
this.spoiler_text = spoiler_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private List<Attachment> media_attachments;
|
||||||
|
private List<Mention> mentions;
|
||||||
|
private List<Tag> tags;
|
||||||
|
private Application application;
|
||||||
|
public List<Attachment> getMedia_attachments() {
|
||||||
|
return media_attachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMedia_attachments(List<Attachment> media_attachments) {
|
||||||
|
this.media_attachments = media_attachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Mention> getMentions() {
|
||||||
|
return mentions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMentions(List<Mention> mentions) {
|
||||||
|
this.mentions = mentions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Tag> getTags() {
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTags(List<Tag> tags) {
|
||||||
|
this.tags = tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Application getApplication() {
|
||||||
|
return application;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplication(Application application) {
|
||||||
|
this.application = application;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getVisibility() {
|
||||||
|
return visibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVisibility(String visibility) {
|
||||||
|
this.visibility = visibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAttachmentShown() {
|
||||||
|
return attachmentShown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentShown(boolean attachmentShown) {
|
||||||
|
this.attachmentShown = attachmentShown;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
* Manage Tags
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Tag {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Error {
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.client;
|
||||||
|
|
||||||
|
import com.loopj.android.http.AsyncHttpClient;
|
||||||
|
import com.loopj.android.http.AsyncHttpResponseHandler;
|
||||||
|
import com.loopj.android.http.RequestParams;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
* Client to call urls
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class OauthClient {
|
||||||
|
|
||||||
|
private static final String BASE_URL = "https://" + Helper.INSTANCE;
|
||||||
|
|
||||||
|
private static AsyncHttpClient client = new AsyncHttpClient();
|
||||||
|
|
||||||
|
public void get(String action, HashMap<String, String> paramaters, AsyncHttpResponseHandler responseHandler) {
|
||||||
|
client.setTimeout(5000);
|
||||||
|
RequestParams params = hashToRequestParams(paramaters);
|
||||||
|
client.get(getAbsoluteUrl(action), params, responseHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void post(String action, HashMap<String, String> paramaters, AsyncHttpResponseHandler responseHandler) {
|
||||||
|
RequestParams params = hashToRequestParams(paramaters);
|
||||||
|
client.post(getAbsoluteUrl(action), params, responseHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getAbsoluteUrl(String action) {
|
||||||
|
return BASE_URL + action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert HashMap<String,String> to RequestParams
|
||||||
|
* @param params HashMap
|
||||||
|
* @return RequestParams
|
||||||
|
*/
|
||||||
|
private RequestParams hashToRequestParams(HashMap<String,String> params){
|
||||||
|
RequestParams requestParams = new RequestParams();
|
||||||
|
Iterator it = params.entrySet().iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Map.Entry pair = (Map.Entry)it.next();
|
||||||
|
requestParams.add(pair.getKey().toString(), pair.getValue().toString());
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
return requestParams;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,247 @@
|
||||||
|
package fr.gouv.etalab.mastodon.drawers;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.design.widget.FloatingActionButton;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.util.Linkify;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.activities.ShowAccountActivity;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.PostActionAsyncTask;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 27/04/2017.
|
||||||
|
* Adapter for accounts
|
||||||
|
*/
|
||||||
|
public class AccountsListAdapter extends BaseAdapter implements OnPostActionInterface {
|
||||||
|
|
||||||
|
private List<Account> accounts;
|
||||||
|
private LayoutInflater layoutInflater;
|
||||||
|
private ImageLoader imageLoader;
|
||||||
|
private DisplayImageOptions options;
|
||||||
|
private RetrieveAccountsAsyncTask.Type action;
|
||||||
|
private Context context;
|
||||||
|
private AccountsListAdapter accountsListAdapter;
|
||||||
|
|
||||||
|
public AccountsListAdapter(Context context, RetrieveAccountsAsyncTask.Type action, List<Account> accounts){
|
||||||
|
this.context = context;
|
||||||
|
this.accounts = accounts;
|
||||||
|
layoutInflater = LayoutInflater.from(context);
|
||||||
|
imageLoader = ImageLoader.getInstance();
|
||||||
|
options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
|
||||||
|
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
|
||||||
|
this.action = action;
|
||||||
|
this.accountsListAdapter = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return accounts.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getItem(int position) {
|
||||||
|
return accounts.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||||
|
|
||||||
|
final Account account = accounts.get(position);
|
||||||
|
final ViewHolder holder;
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = layoutInflater.inflate(R.layout.drawer_account, parent, false);
|
||||||
|
holder = new ViewHolder();
|
||||||
|
holder.account_pp = (ImageView) convertView.findViewById(R.id.account_pp);
|
||||||
|
holder.account_dn = (TextView) convertView.findViewById(R.id.account_dn);
|
||||||
|
holder.account_ac = (TextView) convertView.findViewById(R.id.account_ac);
|
||||||
|
holder.account_un = (TextView) convertView.findViewById(R.id.account_un);
|
||||||
|
holder.account_ds = (TextView) convertView.findViewById(R.id.account_ds);
|
||||||
|
holder.account_sc = (TextView) convertView.findViewById(R.id.account_sc);
|
||||||
|
holder.account_fgc = (TextView) convertView.findViewById(R.id.account_fgc);
|
||||||
|
holder.account_frc = (TextView) convertView.findViewById(R.id.account_frc);
|
||||||
|
holder.account_action_block = (FloatingActionButton) convertView.findViewById(R.id.account_action_block);
|
||||||
|
holder.account_action_mute = (FloatingActionButton) convertView.findViewById(R.id.account_action_mute);
|
||||||
|
|
||||||
|
holder.account_container = (LinearLayout) convertView.findViewById(R.id.account_container);
|
||||||
|
convertView.setTag(holder);
|
||||||
|
} else {
|
||||||
|
holder = (ViewHolder) convertView.getTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( action == RetrieveAccountsAsyncTask.Type.BLOCKED)
|
||||||
|
holder.account_action_block.setVisibility(View.VISIBLE);
|
||||||
|
else if( action == RetrieveAccountsAsyncTask.Type.MUTED)
|
||||||
|
holder.account_action_mute.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
|
||||||
|
holder.account_action_mute.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
moreOptionDialog(account);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.account_action_block.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
moreOptionDialog(account);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
holder.account_container.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if( holder.account_ds.getVisibility() == View.VISIBLE)
|
||||||
|
holder.account_ds.setVisibility(View.GONE);
|
||||||
|
else
|
||||||
|
holder.account_ds.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
holder.account_dn.setText(account.getDisplay_name());
|
||||||
|
holder.account_un.setText(String.format("@%s",account.getUsername()));
|
||||||
|
holder.account_ac.setText(account.getAcct());
|
||||||
|
if( account.getDisplay_name().equals(account.getAcct()))
|
||||||
|
holder.account_ac.setVisibility(View.GONE);
|
||||||
|
else
|
||||||
|
holder.account_ac.setVisibility(View.VISIBLE);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||||
|
holder.account_ds.setText(Html.fromHtml(account.getNote(), Html.FROM_HTML_MODE_COMPACT));
|
||||||
|
else
|
||||||
|
holder.account_ds.setText(Html.fromHtml(account.getNote()));
|
||||||
|
holder.account_ds.setAutoLinkMask(Linkify.WEB_URLS);
|
||||||
|
holder.account_sc.setText(String.valueOf(account.getStatuses_count()));
|
||||||
|
holder.account_fgc.setText(String.valueOf(account.getFollowing_count()));
|
||||||
|
holder.account_frc.setText(String.valueOf(account.getFollowers_count()));
|
||||||
|
//Profile picture
|
||||||
|
imageLoader.displayImage(account.getAvatar(), holder.account_pp, options);
|
||||||
|
|
||||||
|
|
||||||
|
holder.account_pp.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(context, ShowAccountActivity.class);
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.putString("accountId", account.getId());
|
||||||
|
intent.putExtras(b);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPostAction(int statusCode, API.StatusAction statusAction, String targetedId) {
|
||||||
|
Helper.manageMessageStatusCode(context, statusCode, statusAction);
|
||||||
|
//When unmuting or unblocking an account, it is removed from the list
|
||||||
|
List<Account> accountsToRemove = new ArrayList<>();
|
||||||
|
if( statusAction == API.StatusAction.UNMUTE || statusAction == API.StatusAction.UNBLOCK){
|
||||||
|
for(Account account: accounts){
|
||||||
|
if( account.getId().equals(targetedId))
|
||||||
|
accountsToRemove.add(account);
|
||||||
|
}
|
||||||
|
accounts.removeAll(accountsToRemove);
|
||||||
|
accountsListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class ViewHolder {
|
||||||
|
ImageView account_pp;
|
||||||
|
TextView account_ac;
|
||||||
|
TextView account_dn;
|
||||||
|
TextView account_un;
|
||||||
|
TextView account_ds;
|
||||||
|
TextView account_sc;
|
||||||
|
TextView account_fgc;
|
||||||
|
TextView account_frc;
|
||||||
|
LinearLayout account_container;
|
||||||
|
FloatingActionButton account_action_block;
|
||||||
|
FloatingActionButton account_action_mute;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* More option for acccounts (unmute / unblock)
|
||||||
|
* @param account Account current account
|
||||||
|
*/
|
||||||
|
private void moreOptionDialog(final Account account){
|
||||||
|
|
||||||
|
String[] stringArrayConf = context.getResources().getStringArray(R.array.more_action_confirm_account);
|
||||||
|
final API.StatusAction doAction;
|
||||||
|
|
||||||
|
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
|
||||||
|
|
||||||
|
if( action == RetrieveAccountsAsyncTask.Type.BLOCKED) {
|
||||||
|
dialog.setMessage(stringArrayConf[1]);
|
||||||
|
doAction = API.StatusAction.UNBLOCK;
|
||||||
|
}else {
|
||||||
|
dialog.setMessage(stringArrayConf[0]);
|
||||||
|
doAction = API.StatusAction.UNMUTE;
|
||||||
|
}
|
||||||
|
dialog.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog,int which) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog,int which) {
|
||||||
|
new PostActionAsyncTask(context, doAction, account.getId(), AccountsListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
package fr.gouv.etalab.mastodon.drawers;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
|
||||||
|
import java.util.List;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 05/05/2017.
|
||||||
|
* Adapter for accounts when searching
|
||||||
|
*/
|
||||||
|
public class AccountsSearchAdapter extends BaseAdapter {
|
||||||
|
|
||||||
|
private List<Account> accounts;
|
||||||
|
private LayoutInflater layoutInflater;
|
||||||
|
private ImageLoader imageLoader;
|
||||||
|
private DisplayImageOptions options;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
public AccountsSearchAdapter(Context context, List<Account> accounts){
|
||||||
|
this.accounts = accounts;
|
||||||
|
layoutInflater = LayoutInflater.from(context);
|
||||||
|
imageLoader = ImageLoader.getInstance();
|
||||||
|
this.context = context;
|
||||||
|
options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
|
||||||
|
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return accounts.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getItem(int position) {
|
||||||
|
return accounts.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||||
|
|
||||||
|
final Account account = accounts.get(position);
|
||||||
|
final ViewHolder holder;
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = layoutInflater.inflate(R.layout.drawer_account_search, parent, false);
|
||||||
|
holder = new ViewHolder();
|
||||||
|
holder.account_pp = (ImageView) convertView.findViewById(R.id.account_pp);
|
||||||
|
holder.account_dn = (TextView) convertView.findViewById(R.id.account_dn);
|
||||||
|
holder.account_un = (TextView) convertView.findViewById(R.id.account_un);
|
||||||
|
|
||||||
|
holder.account_container = (LinearLayout) convertView.findViewById(R.id.account_container);
|
||||||
|
convertView.setTag(holder);
|
||||||
|
} else {
|
||||||
|
holder = (ViewHolder) convertView.getTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.account_dn.setText(account.getDisplay_name());
|
||||||
|
holder.account_un.setText(String.format("@%s",account.getUsername()));
|
||||||
|
//Profile picture
|
||||||
|
imageLoader.displayImage(account.getAvatar(), holder.account_pp, options);
|
||||||
|
|
||||||
|
holder.account_container.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(Helper.SEARCH_VALIDATE_ACCOUNT);
|
||||||
|
intent.putExtra("acct", account.getAcct());
|
||||||
|
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class ViewHolder {
|
||||||
|
ImageView account_pp;
|
||||||
|
TextView account_dn;
|
||||||
|
TextView account_un;
|
||||||
|
LinearLayout account_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,249 @@
|
||||||
|
package fr.gouv.etalab.mastodon.drawers;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.util.Linkify;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.VideoView;
|
||||||
|
|
||||||
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||||
|
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
|
||||||
|
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.activities.ShowAccountActivity;
|
||||||
|
import fr.gouv.etalab.mastodon.activities.ShowConversationActivity;
|
||||||
|
import fr.gouv.etalab.mastodon.activities.TootActivity;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Attachment;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Status;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 24/04/2017.
|
||||||
|
* Adapter for Status
|
||||||
|
*/
|
||||||
|
public class NotificationsListAdapter extends BaseAdapter {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private List<Notification> notifications;
|
||||||
|
private LayoutInflater layoutInflater;
|
||||||
|
private ImageLoader imageLoader;
|
||||||
|
private DisplayImageOptions options;
|
||||||
|
|
||||||
|
public NotificationsListAdapter(Context context, List<Notification> notifications){
|
||||||
|
this.context = context;
|
||||||
|
this.notifications = notifications;
|
||||||
|
layoutInflater = LayoutInflater.from(this.context);
|
||||||
|
imageLoader = ImageLoader.getInstance();
|
||||||
|
options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
|
||||||
|
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return notifications.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getItem(int position) {
|
||||||
|
return notifications.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||||
|
|
||||||
|
final Notification notification = notifications.get(position);
|
||||||
|
final ViewHolder holder;
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = layoutInflater.inflate(R.layout.drawer_notification, parent, false);
|
||||||
|
holder = new ViewHolder();
|
||||||
|
holder.notification_status_container = (LinearLayout) convertView.findViewById(R.id.notification_status_container);
|
||||||
|
holder.status_document_container = (LinearLayout) convertView.findViewById(R.id.status_document_container);
|
||||||
|
holder.notification_status_content = (TextView) convertView.findViewById(R.id.notification_status_content);
|
||||||
|
holder.notification_account_username = (TextView) convertView.findViewById(R.id.notification_account_username);
|
||||||
|
holder.notification_type = (TextView) convertView.findViewById(R.id.notification_type);
|
||||||
|
holder.notification_account_displayname = (TextView) convertView.findViewById(R.id.notification_account_displayname);
|
||||||
|
holder.notification_account_profile = (ImageView) convertView.findViewById(R.id.notification_account_profile);
|
||||||
|
holder.status_favorite_count = (TextView) convertView.findViewById(R.id.status_favorite_count);
|
||||||
|
holder.status_reblog_count = (TextView) convertView.findViewById(R.id.status_reblog_count);
|
||||||
|
holder.status_date = (TextView) convertView.findViewById(R.id.status_date);
|
||||||
|
holder.status_reply = (ImageView) convertView.findViewById(R.id.status_reply);
|
||||||
|
holder.status_privacy = (ImageView) convertView.findViewById(R.id.status_privacy);
|
||||||
|
convertView.setTag(holder);
|
||||||
|
} else {
|
||||||
|
holder = (ViewHolder) convertView.getTag();
|
||||||
|
}
|
||||||
|
final float scale = context.getResources().getDisplayMetrics().density;
|
||||||
|
String type = notification.getType();
|
||||||
|
String typeString = "";
|
||||||
|
switch (type){
|
||||||
|
case "mention":
|
||||||
|
typeString = String.format("@%s %s", notification.getAccount().getAcct(),context.getString(R.string.notif_mention));
|
||||||
|
break;
|
||||||
|
case "reblog":
|
||||||
|
typeString = String.format("@%s %s", notification.getAccount().getAcct(),context.getString(R.string.notif_reblog));
|
||||||
|
break;
|
||||||
|
case "favourite":
|
||||||
|
typeString = String.format("@%s %s", notification.getAccount().getAcct(),context.getString(R.string.notif_favourite));
|
||||||
|
break;
|
||||||
|
case "follow":
|
||||||
|
typeString = String.format("@%s %s", notification.getAccount().getAcct(),context.getString(R.string.notif_follow));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
holder.notification_type.setText(typeString);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
final Status status = notification.getStatus();
|
||||||
|
if( status != null){
|
||||||
|
if( status.getMedia_attachments().size() < 1)
|
||||||
|
holder.status_document_container.setVisibility(View.GONE);
|
||||||
|
else
|
||||||
|
holder.status_document_container.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
if( !status.getIn_reply_to_account_id().equals("null") || !status.getIn_reply_to_id().equals("null") ){
|
||||||
|
Drawable img = ContextCompat.getDrawable(context, R.drawable.ic_reply);
|
||||||
|
img.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (15 * scale + 0.5f));
|
||||||
|
holder.notification_account_displayname.setCompoundDrawables( img, null, null, null);
|
||||||
|
}else if( status.isReblogged()){
|
||||||
|
Drawable img = ContextCompat.getDrawable(context, R.drawable.ic_retweet);
|
||||||
|
img.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (15 * scale + 0.5f));
|
||||||
|
holder.notification_account_displayname.setCompoundDrawables( img, null, null, null);
|
||||||
|
}else{
|
||||||
|
holder.notification_account_displayname.setCompoundDrawables( null, null, null, null);
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||||
|
holder.notification_status_content.setText(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT));
|
||||||
|
else
|
||||||
|
holder.notification_status_content.setText(Html.fromHtml(status.getContent()));
|
||||||
|
holder.notification_status_content.setAutoLinkMask(Linkify.WEB_URLS);
|
||||||
|
holder.status_favorite_count.setText(String.valueOf(status.getFavourites_count()));
|
||||||
|
holder.status_reblog_count.setText(String.valueOf(status.getReblogs_count()));
|
||||||
|
holder.status_date.setText(Helper.dateDiff(context, status.getCreated_at()));
|
||||||
|
|
||||||
|
|
||||||
|
//Adds attachment -> disabled, to enable them uncomment the line below
|
||||||
|
//loadAttachments(status, holder);
|
||||||
|
holder.notification_status_container.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
if( !status.getIn_reply_to_account_id().equals("null") || !status.getIn_reply_to_id().equals("null") ) {
|
||||||
|
holder.notification_status_content.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(context, ShowConversationActivity.class);
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.putString("statusId", status.getId()); //Your id
|
||||||
|
intent.putExtras(b); //Put your id to your next Intent
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
switch (status.getVisibility()){
|
||||||
|
case "public":
|
||||||
|
holder.status_privacy.setImageResource(R.drawable.ic_action_globe);
|
||||||
|
break;
|
||||||
|
case "unlisted":
|
||||||
|
holder.status_privacy.setImageResource(R.drawable.ic_action_lock_open);
|
||||||
|
break;
|
||||||
|
case "private":
|
||||||
|
holder.status_privacy.setImageResource(R.drawable.ic_action_lock_closed);
|
||||||
|
break;
|
||||||
|
case "direct":
|
||||||
|
holder.status_privacy.setImageResource(R.drawable.ic_local_post_office);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
holder.notification_status_container.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
holder.notification_account_profile.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(context, ShowAccountActivity.class);
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.putString("accountId", notification.getAccount().getId());
|
||||||
|
intent.putExtras(b);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
holder.status_reply.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(context, TootActivity.class);
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.putString("inReplyTo", notification.getStatus().getId()); //Your id
|
||||||
|
intent.putExtras(b); //Put your id to your next Intent
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
holder.notification_account_displayname.setText(notification.getAccount().getDisplay_name());
|
||||||
|
holder.notification_account_username.setText( String.format("@%s",notification.getAccount().getUsername()));
|
||||||
|
//Profile picture
|
||||||
|
imageLoader.displayImage(notification.getAccount().getAvatar(), holder.notification_account_profile, options);
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class ViewHolder {
|
||||||
|
TextView notification_status_content;
|
||||||
|
TextView notification_type;
|
||||||
|
TextView notification_account_username;
|
||||||
|
TextView notification_account_displayname;
|
||||||
|
ImageView notification_account_profile;
|
||||||
|
TextView status_favorite_count;
|
||||||
|
TextView status_reblog_count;
|
||||||
|
TextView status_date;
|
||||||
|
ImageView status_reply;
|
||||||
|
LinearLayout status_document_container;
|
||||||
|
LinearLayout notification_status_container;
|
||||||
|
ImageView status_privacy;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,718 @@
|
||||||
|
package fr.gouv.etalab.mastodon.drawers;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.media.MediaPlayer;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.util.Linkify;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.VideoView;
|
||||||
|
|
||||||
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||||
|
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
|
||||||
|
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.activities.MainActivity;
|
||||||
|
import fr.gouv.etalab.mastodon.activities.ShowConversationActivity;
|
||||||
|
import fr.gouv.etalab.mastodon.activities.TootActivity;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.activities.ShowAccountActivity;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.PostActionAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Attachment;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Status;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface;
|
||||||
|
|
||||||
|
import static fr.gouv.etalab.mastodon.helper.Helper.EXTERNAL_STORAGE_REQUEST_CODE;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 24/04/2017.
|
||||||
|
* Adapter for Status
|
||||||
|
*/
|
||||||
|
public class StatusListAdapter extends BaseAdapter implements OnPostActionInterface {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private List<Status> statuses;
|
||||||
|
private LayoutInflater layoutInflater;
|
||||||
|
private ImageLoader imageLoader;
|
||||||
|
private DisplayImageOptions options;
|
||||||
|
private boolean isOnWifi;
|
||||||
|
private int behaviorWithAttachments;
|
||||||
|
private StatusListAdapter statusListAdapter;
|
||||||
|
private final int REBLOG = 1;
|
||||||
|
private final int FAVOURITE = 2;
|
||||||
|
private ViewHolder holder;
|
||||||
|
private RetrieveFeedsAsyncTask.Type type;
|
||||||
|
|
||||||
|
public StatusListAdapter(Context context, RetrieveFeedsAsyncTask.Type type, boolean isOnWifi, int behaviorWithAttachments, List<Status> statuses){
|
||||||
|
this.context = context;
|
||||||
|
this.statuses = statuses;
|
||||||
|
this.isOnWifi = isOnWifi;
|
||||||
|
this.behaviorWithAttachments = behaviorWithAttachments;
|
||||||
|
layoutInflater = LayoutInflater.from(this.context);
|
||||||
|
imageLoader = ImageLoader.getInstance();
|
||||||
|
options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
|
||||||
|
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
|
||||||
|
statusListAdapter = this;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return statuses.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getItem(int position) {
|
||||||
|
return statuses.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||||
|
|
||||||
|
final Status status = statuses.get(position);
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = layoutInflater.inflate(R.layout.drawer_status, parent, false);
|
||||||
|
holder = new ViewHolder();
|
||||||
|
holder.status_document_container = (LinearLayout) convertView.findViewById(R.id.status_document_container);
|
||||||
|
holder.status_content = (TextView) convertView.findViewById(R.id.status_content);
|
||||||
|
holder.status_account_username = (TextView) convertView.findViewById(R.id.status_account_username);
|
||||||
|
holder.status_account_displayname = (TextView) convertView.findViewById(R.id.status_account_displayname);
|
||||||
|
holder.status_account_profile = (ImageView) convertView.findViewById(R.id.status_account_profile);
|
||||||
|
holder.status_favorite_count = (TextView) convertView.findViewById(R.id.status_favorite_count);
|
||||||
|
holder.status_reblog_count = (TextView) convertView.findViewById(R.id.status_reblog_count);
|
||||||
|
holder.status_toot_date = (TextView) convertView.findViewById(R.id.status_toot_date);
|
||||||
|
holder.status_show_more = (Button) convertView.findViewById(R.id.status_show_more);
|
||||||
|
holder.status_more = (ImageView) convertView.findViewById(R.id.status_more);
|
||||||
|
holder.status_reblog_user = (TextView) convertView.findViewById(R.id.status_reblog_user);
|
||||||
|
holder.status_action_container = (LinearLayout) convertView.findViewById(R.id.status_action_container);
|
||||||
|
holder.status_prev1 = (ImageView) convertView.findViewById(R.id.status_prev1);
|
||||||
|
holder.status_prev2 = (ImageView) convertView.findViewById(R.id.status_prev2);
|
||||||
|
holder.status_prev3 = (ImageView) convertView.findViewById(R.id.status_prev3);
|
||||||
|
holder.status_prev4 = (ImageView) convertView.findViewById(R.id.status_prev4);
|
||||||
|
holder.status_container2 = (LinearLayout) convertView.findViewById(R.id.status_container2);
|
||||||
|
holder.status_container3 = (LinearLayout) convertView.findViewById(R.id.status_container3);
|
||||||
|
holder.status_reply = (ImageView) convertView.findViewById(R.id.status_reply);
|
||||||
|
holder.status_privacy = (ImageView) convertView.findViewById(R.id.status_privacy);
|
||||||
|
holder.main_container = (LinearLayout) convertView.findViewById(R.id.main_container);
|
||||||
|
convertView.setTag(holder);
|
||||||
|
} else {
|
||||||
|
holder = (ViewHolder) convertView.getTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Hides action bottom bar action when looking to status trough accounts
|
||||||
|
if( type == RetrieveFeedsAsyncTask.Type.USER){
|
||||||
|
holder.status_action_container.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
final float scale = context.getResources().getDisplayMetrics().density;
|
||||||
|
if( !status.getIn_reply_to_account_id().equals("null") || !status.getIn_reply_to_id().equals("null") ){
|
||||||
|
Drawable img = ContextCompat.getDrawable(context, R.drawable.ic_reply);
|
||||||
|
img.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (15 * scale + 0.5f));
|
||||||
|
holder.status_account_displayname.setCompoundDrawables( img, null, null, null);
|
||||||
|
}else if( status.getReblog() != null){
|
||||||
|
Drawable img = ContextCompat.getDrawable(context, R.drawable.ic_retweet_header);
|
||||||
|
img.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (15 * scale + 0.5f));
|
||||||
|
holder.status_account_displayname.setCompoundDrawables( img, null, null, null);
|
||||||
|
}else{
|
||||||
|
holder.status_account_displayname.setCompoundDrawables( null, null, null, null);
|
||||||
|
}
|
||||||
|
//Click on a conversation
|
||||||
|
if( type != RetrieveFeedsAsyncTask.Type.CONTEXT ){
|
||||||
|
if( !status.getIn_reply_to_account_id().equals("null") || !status.getIn_reply_to_id().equals("null") ) {
|
||||||
|
holder.status_content.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(context, ShowConversationActivity.class);
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.putString("statusId", status.getId()); //Your id
|
||||||
|
intent.putExtras(b); //Put your id to your next Intent
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
holder.status_content.setOnClickListener(null);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
if( position == ShowConversationActivity.position){
|
||||||
|
holder.main_container.setBackgroundResource(R.color.blue_light);
|
||||||
|
}else {
|
||||||
|
holder.main_container.setBackgroundResource(R.color.white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final String content, displayName, username, ppurl;
|
||||||
|
if( status.getReblog() != null){
|
||||||
|
content = status.getReblog().getContent();
|
||||||
|
displayName = status.getReblog().getAccount().getDisplay_name();
|
||||||
|
username = status.getReblog().getAccount().getUsername();
|
||||||
|
holder.status_reblog_user.setText(displayName + " " +String.format("@%s",username));
|
||||||
|
ppurl = status.getReblog().getAccount().getAvatar();
|
||||||
|
holder.status_reblog_user.setVisibility(View.VISIBLE);
|
||||||
|
holder.status_account_displayname.setText(context.getResources().getString(R.string.reblog_by, status.getAccount().getAcct()));
|
||||||
|
holder.status_account_username.setText( "");
|
||||||
|
}else {
|
||||||
|
ppurl = status.getAccount().getAvatar();
|
||||||
|
content = status.getContent();
|
||||||
|
displayName = status.getAccount().getDisplay_name();
|
||||||
|
username = status.getAccount().getUsername();
|
||||||
|
holder.status_reblog_user.setVisibility(View.GONE);
|
||||||
|
holder.status_account_displayname.setText(displayName);
|
||||||
|
holder.status_account_username.setText( String.format("@%s",username));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
holder.status_reply.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(context, TootActivity.class);
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.putString("inReplyTo", status.getId()); //Your id
|
||||||
|
intent.putExtras(b); //Put your id to your next Intent
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||||
|
holder.status_content.setText(Html.fromHtml(content, Html.FROM_HTML_MODE_COMPACT));
|
||||||
|
else
|
||||||
|
//noinspection deprecation
|
||||||
|
holder.status_content.setText(Html.fromHtml(content));
|
||||||
|
holder.status_content.setAutoLinkMask(Linkify.WEB_URLS);
|
||||||
|
holder.status_favorite_count.setText(String.valueOf(status.getFavourites_count()));
|
||||||
|
holder.status_reblog_count.setText(String.valueOf(status.getReblogs_count()));
|
||||||
|
holder.status_toot_date.setText(Helper.dateDiff(context, status.getCreated_at()));
|
||||||
|
|
||||||
|
imageLoader.displayImage(ppurl, holder.status_account_profile, options);
|
||||||
|
|
||||||
|
if( status.getMedia_attachments().size() < 1) {
|
||||||
|
holder.status_document_container.setVisibility(View.GONE);
|
||||||
|
holder.status_show_more.setVisibility(View.GONE);
|
||||||
|
}else{
|
||||||
|
if(behaviorWithAttachments == Helper.ATTACHMENT_ALWAYS || ( behaviorWithAttachments == Helper.ATTACHMENT_WIFI && isOnWifi)){
|
||||||
|
loadAttachments(status);
|
||||||
|
holder.status_show_more.setVisibility(View.GONE);
|
||||||
|
status.setAttachmentShown(true);
|
||||||
|
}else{
|
||||||
|
if( !status.isAttachmentShown() ) {
|
||||||
|
holder.status_show_more.setVisibility(View.VISIBLE);
|
||||||
|
holder.status_document_container.setVisibility(View.GONE);
|
||||||
|
}else {
|
||||||
|
loadAttachments(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (status.getVisibility()){
|
||||||
|
case "public":
|
||||||
|
holder.status_privacy.setImageResource(R.drawable.ic_action_globe);
|
||||||
|
break;
|
||||||
|
case "unlisted":
|
||||||
|
holder.status_privacy.setImageResource(R.drawable.ic_action_lock_open);
|
||||||
|
break;
|
||||||
|
case "private":
|
||||||
|
holder.status_privacy.setImageResource(R.drawable.ic_action_lock_closed);
|
||||||
|
break;
|
||||||
|
case "direct":
|
||||||
|
holder.status_privacy.setImageResource(R.drawable.ic_local_post_office);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Drawable imgFav, imgReblog;
|
||||||
|
if( status.isFavourited())
|
||||||
|
imgFav = ContextCompat.getDrawable(context, R.drawable.ic_fav_yellow);
|
||||||
|
else
|
||||||
|
imgFav = ContextCompat.getDrawable(context, R.drawable.ic_fav_black);
|
||||||
|
|
||||||
|
if( status.isReblogged())
|
||||||
|
imgReblog = ContextCompat.getDrawable(context, R.drawable.ic_retweet_yellow);
|
||||||
|
else
|
||||||
|
imgReblog = ContextCompat.getDrawable(context, R.drawable.ic_retweet_black);
|
||||||
|
|
||||||
|
imgFav.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (20 * scale + 0.5f));
|
||||||
|
imgReblog.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (15 * scale + 0.5f));
|
||||||
|
holder.status_favorite_count.setCompoundDrawables(imgFav, null, null, null);
|
||||||
|
holder.status_reblog_count.setCompoundDrawables(imgReblog, null, null, null);
|
||||||
|
|
||||||
|
holder.status_show_more.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
loadAttachments(status);
|
||||||
|
holder.status_show_more.setVisibility(View.GONE);
|
||||||
|
status.setAttachmentShown(true);
|
||||||
|
statusListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.status_favorite_count.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
boolean confirmation = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION, true);
|
||||||
|
if( confirmation )
|
||||||
|
displayConfirmationDialog(FAVOURITE,status);
|
||||||
|
else
|
||||||
|
favouriteAction(status);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.status_reblog_count.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
boolean confirmation = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION, true);
|
||||||
|
if( confirmation )
|
||||||
|
displayConfirmationDialog(REBLOG,status);
|
||||||
|
else
|
||||||
|
favouriteAction(status);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.status_more.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
moreOptionDialog(status);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
holder.status_account_profile.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(context, ShowAccountActivity.class);
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.putString("accountId", status.getAccount().getId());
|
||||||
|
intent.putExtras(b);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Profile picture
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Favourites/Unfavourites a status
|
||||||
|
* @param status Status
|
||||||
|
*/
|
||||||
|
private void favouriteAction(Status status){
|
||||||
|
if( status.isFavourited()){
|
||||||
|
new PostActionAsyncTask(context, API.StatusAction.UNFAVOURITE, status.getId(), StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
status.setFavourited(false);
|
||||||
|
}else{
|
||||||
|
new PostActionAsyncTask(context, API.StatusAction.FAVOURITE, status.getId(), StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
status.setFavourited(true);
|
||||||
|
}
|
||||||
|
statusListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reblog/Unreblog a status
|
||||||
|
* @param status Status
|
||||||
|
*/
|
||||||
|
private void reblogAction(Status status){
|
||||||
|
if( status.isReblogged()){
|
||||||
|
new PostActionAsyncTask(context, API.StatusAction.UNREBLOG, status.getId(), StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
status.setReblogged(false);
|
||||||
|
}else{
|
||||||
|
new PostActionAsyncTask(context, API.StatusAction.REBLOG, status.getId(), StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
status.setReblogged(true);
|
||||||
|
}
|
||||||
|
statusListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void loadAttachments(final Status status){
|
||||||
|
List<Attachment> attachments = status.getMedia_attachments();
|
||||||
|
if( attachments != null && attachments.size() > 0){
|
||||||
|
int i = 0;
|
||||||
|
if( attachments.size() == 1){
|
||||||
|
holder.status_container2.setVisibility(View.GONE);
|
||||||
|
}else if(attachments.size() == 2){
|
||||||
|
holder.status_container2.setVisibility(View.VISIBLE);
|
||||||
|
holder.status_container3.setVisibility(View.GONE);
|
||||||
|
}else if( attachments.size() == 3){
|
||||||
|
holder.status_container2.setVisibility(View.VISIBLE);
|
||||||
|
holder.status_container3.setVisibility(View.VISIBLE);
|
||||||
|
holder.status_prev4.setVisibility(View.GONE);
|
||||||
|
}else {
|
||||||
|
holder.status_prev4.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
for(final Attachment attachment: attachments){
|
||||||
|
ImageView imageView;
|
||||||
|
if( i == 0)
|
||||||
|
imageView = holder.status_prev1;
|
||||||
|
else if( i == 1)
|
||||||
|
imageView = holder.status_prev2;
|
||||||
|
else if(i == 2)
|
||||||
|
imageView = holder.status_prev3;
|
||||||
|
else
|
||||||
|
imageView = holder.status_prev4;
|
||||||
|
String url = attachment.getPreview_url();
|
||||||
|
if( url == null || url.trim().equals(""))
|
||||||
|
url = attachment.getUrl();
|
||||||
|
imageLoader.displayImage(url, imageView, options);
|
||||||
|
imageView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
showPicture(attachment);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
holder.status_document_container.setVisibility(View.VISIBLE);
|
||||||
|
}else{
|
||||||
|
holder.status_document_container.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
holder.status_show_more.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showPicture(final Attachment attachment) {
|
||||||
|
|
||||||
|
final AlertDialog.Builder alertadd = new AlertDialog.Builder(context);
|
||||||
|
LayoutInflater factory = LayoutInflater.from(context);
|
||||||
|
final View view = factory.inflate(R.layout.show_attachment, null);
|
||||||
|
alertadd.setView(view);
|
||||||
|
final RelativeLayout loader = (RelativeLayout) view.findViewById(R.id.loader);
|
||||||
|
switch (attachment.getType()){
|
||||||
|
case "image": {
|
||||||
|
String url = attachment.getRemote_url();
|
||||||
|
if(url == null || url.trim().equals(""))
|
||||||
|
url = attachment.getUrl();
|
||||||
|
final ImageView imageView = (ImageView) view.findViewById(R.id.dialog_imageview);
|
||||||
|
imageLoader.displayImage(url, imageView, options, new SimpleImageLoadingListener(){
|
||||||
|
@Override
|
||||||
|
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
|
||||||
|
super.onLoadingComplete(imageUri, view, loadedImage);
|
||||||
|
loader.setVisibility(View.GONE);
|
||||||
|
imageView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onLoadingFailed(java.lang.String imageUri, android.view.View view, FailReason failReason){
|
||||||
|
imageLoader.displayImage(attachment.getPreview_url(), imageView, options);
|
||||||
|
loader.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "gifv":
|
||||||
|
case "video": {
|
||||||
|
if( attachment.getRemote_url().contains(".gif") ){
|
||||||
|
view.findViewById(R.id.dialog_webview_container).setVisibility(View.VISIBLE);
|
||||||
|
WebView webView = (WebView) view.findViewById(R.id.dialog_webview);
|
||||||
|
webView.getSettings().setJavaScriptEnabled(false);
|
||||||
|
webView.clearCache(false);
|
||||||
|
webView.setScrollbarFadingEnabled(true);
|
||||||
|
webView.getSettings().setBuiltInZoomControls(false);
|
||||||
|
webView.getSettings().setSupportZoom(false);
|
||||||
|
webView.getSettings().setUseWideViewPort(false);
|
||||||
|
webView.setVerticalScrollBarEnabled(false);
|
||||||
|
webView.setHorizontalScrollBarEnabled(false);
|
||||||
|
webView.setInitialScale(0);
|
||||||
|
String url = attachment.getRemote_url();
|
||||||
|
if(url == null || url.trim().equals(""))
|
||||||
|
url = attachment.getUrl();
|
||||||
|
webView.loadUrl(url);
|
||||||
|
loader.setVisibility(View.GONE);
|
||||||
|
}else {
|
||||||
|
String url = attachment.getRemote_url();
|
||||||
|
if(url == null || url.trim().equals(""))
|
||||||
|
url = attachment.getUrl();
|
||||||
|
Uri uri = Uri.parse(url);
|
||||||
|
VideoView videoView = (VideoView) view.findViewById(R.id.dialog_videoview);
|
||||||
|
videoView.setVisibility(View.VISIBLE);
|
||||||
|
videoView.setVideoURI(uri);
|
||||||
|
videoView.start();
|
||||||
|
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
|
||||||
|
@Override
|
||||||
|
public void onPrepared(MediaPlayer mp) {
|
||||||
|
loader.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alertadd.setPositiveButton(R.string.download, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dlg, int sumthin) {
|
||||||
|
if(Build.VERSION.SDK_INT >= 23 ){
|
||||||
|
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {
|
||||||
|
ActivityCompat.requestPermissions((MainActivity)context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, EXTERNAL_STORAGE_REQUEST_CODE);
|
||||||
|
} else {
|
||||||
|
Helper.manageDownloads(context, attachment.getRemote_url());
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Helper.manageDownloads(context, attachment.getRemote_url());
|
||||||
|
}
|
||||||
|
dlg.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
alertadd.setNeutralButton(R.string.close, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dlg, int sumthin) {
|
||||||
|
dlg.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
alertadd.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPostAction(int statusCode,API.StatusAction statusAction, String targetedId) {
|
||||||
|
Helper.manageMessageStatusCode(context, statusCode, statusAction);
|
||||||
|
//When muting or blocking an account, its status are removed from the list
|
||||||
|
List<Status> statusesToRemove = new ArrayList<>();
|
||||||
|
if( statusAction == API.StatusAction.MUTE || statusAction == API.StatusAction.BLOCK){
|
||||||
|
for(Status status: statuses){
|
||||||
|
if( status.getAccount().getId().equals(targetedId))
|
||||||
|
statusesToRemove.add(status);
|
||||||
|
}
|
||||||
|
statuses.removeAll(statusesToRemove);
|
||||||
|
statusListAdapter.notifyDataSetChanged();
|
||||||
|
}else if( statusAction == API.StatusAction.UNSTATUS ){
|
||||||
|
for(Status status: statuses){
|
||||||
|
if( status.getId().equals(targetedId))
|
||||||
|
statusesToRemove.add(status);
|
||||||
|
}
|
||||||
|
statuses.removeAll(statusesToRemove);
|
||||||
|
statusListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private class ViewHolder {
|
||||||
|
TextView status_content;
|
||||||
|
TextView status_account_username;
|
||||||
|
TextView status_account_displayname;
|
||||||
|
ImageView status_account_profile;
|
||||||
|
TextView status_favorite_count;
|
||||||
|
TextView status_reblog_count;
|
||||||
|
TextView status_toot_date;
|
||||||
|
TextView status_reblog_user;
|
||||||
|
Button status_show_more;
|
||||||
|
ImageView status_more;
|
||||||
|
LinearLayout status_action_container;
|
||||||
|
LinearLayout status_document_container;
|
||||||
|
ImageView status_prev1;
|
||||||
|
ImageView status_prev2;
|
||||||
|
ImageView status_prev3;
|
||||||
|
ImageView status_prev4;
|
||||||
|
ImageView status_reply;
|
||||||
|
ImageView status_privacy;
|
||||||
|
LinearLayout status_container2;
|
||||||
|
LinearLayout status_container3;
|
||||||
|
LinearLayout main_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a validation message
|
||||||
|
* @param action int
|
||||||
|
* @param status Status
|
||||||
|
*/
|
||||||
|
private void displayConfirmationDialog(final int action, final Status status){
|
||||||
|
|
||||||
|
String title = null;
|
||||||
|
if( action == FAVOURITE){
|
||||||
|
if( status.isFavourited())
|
||||||
|
title = context.getString(R.string.favourite_remove);
|
||||||
|
else
|
||||||
|
title = context.getString(R.string.favourite_add);
|
||||||
|
}else if( action == REBLOG ){
|
||||||
|
if( status.isReblogged())
|
||||||
|
title = context.getString(R.string.reblog_remove);
|
||||||
|
else
|
||||||
|
title = context.getString(R.string.reblog_add);
|
||||||
|
}
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||||
|
builder.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT));
|
||||||
|
else
|
||||||
|
//noinspection deprecation
|
||||||
|
builder.setMessage(Html.fromHtml(status.getContent()));
|
||||||
|
builder.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
|
.setTitle(title)
|
||||||
|
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
if( action == REBLOG)
|
||||||
|
reblogAction(status);
|
||||||
|
else if( action == FAVOURITE)
|
||||||
|
favouriteAction(status);
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* More option for status (report / remove status / Mute / Block)
|
||||||
|
* @param status Status current status
|
||||||
|
*/
|
||||||
|
private void moreOptionDialog(final Status status){
|
||||||
|
|
||||||
|
|
||||||
|
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
|
||||||
|
final boolean isOwner = status.getAccount().getId().equals(userId);
|
||||||
|
AlertDialog.Builder builderSingle = new AlertDialog.Builder(context);
|
||||||
|
builderSingle.setTitle(R.string.make_a_choice);
|
||||||
|
final String[] stringArray, stringArrayConf;
|
||||||
|
final API.StatusAction[] doAction;
|
||||||
|
if( isOwner) {
|
||||||
|
stringArray = context.getResources().getStringArray(R.array.more_action_owner);
|
||||||
|
stringArrayConf = context.getResources().getStringArray(R.array.more_action_owner_confirm);
|
||||||
|
doAction = new API.StatusAction[]{API.StatusAction.UNSTATUS};
|
||||||
|
|
||||||
|
}else {
|
||||||
|
stringArray = context.getResources().getStringArray(R.array.more_action);
|
||||||
|
stringArrayConf = context.getResources().getStringArray(R.array.more_action_confirm);
|
||||||
|
doAction = new API.StatusAction[]{API.StatusAction.MUTE,API.StatusAction.BLOCK,API.StatusAction.REPORT};
|
||||||
|
}
|
||||||
|
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, stringArray);
|
||||||
|
builderSingle.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
builderSingle.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
AlertDialog.Builder builderInner = new AlertDialog.Builder(context);
|
||||||
|
builderInner.setTitle(stringArrayConf[which]);
|
||||||
|
if( isOwner) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||||
|
builderInner.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT));
|
||||||
|
else
|
||||||
|
//noinspection deprecation
|
||||||
|
builderInner.setMessage(Html.fromHtml(status.getContent()));
|
||||||
|
}else {
|
||||||
|
if( which < 2 ){
|
||||||
|
builderInner.setMessage(status.getAccount().getAcct());
|
||||||
|
}else {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||||
|
builderInner.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_COMPACT));
|
||||||
|
else
|
||||||
|
//noinspection deprecation
|
||||||
|
builderInner.setMessage(Html.fromHtml(status.getContent()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Text for report
|
||||||
|
EditText input = null;
|
||||||
|
final int position = which;
|
||||||
|
if( doAction[which] == API.StatusAction.REPORT){
|
||||||
|
input = new EditText(context);
|
||||||
|
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||||
|
input.setLayoutParams(lp);
|
||||||
|
builderInner.setView(input);
|
||||||
|
}
|
||||||
|
builderInner.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog,int which) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
final EditText finalInput = input;
|
||||||
|
builderInner.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog,int which) {
|
||||||
|
API.StatusAction statusAction = doAction[position];
|
||||||
|
if(statusAction == API.StatusAction.REPORT || statusAction == API.StatusAction.CREATESTATUS){
|
||||||
|
String comment = null;
|
||||||
|
if( finalInput != null && finalInput.getText() != null)
|
||||||
|
comment = finalInput.getText().toString();
|
||||||
|
new PostActionAsyncTask(context, statusAction, status.getId(), status, comment, StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}else{
|
||||||
|
String targetedId;
|
||||||
|
if( doAction[position] == API.StatusAction.FAVOURITE ||
|
||||||
|
doAction[position] == API.StatusAction.UNFAVOURITE ||
|
||||||
|
doAction[position] == API.StatusAction.REBLOG ||
|
||||||
|
doAction[position] == API.StatusAction.UNREBLOG ||
|
||||||
|
doAction[position] == API.StatusAction.UNSTATUS
|
||||||
|
)
|
||||||
|
targetedId = status.getId();
|
||||||
|
else
|
||||||
|
targetedId = status.getAccount().getId();
|
||||||
|
new PostActionAsyncTask(context, statusAction, targetedId, StatusListAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builderInner.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builderSingle.show();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,188 @@
|
||||||
|
package fr.gouv.etalab.mastodon.fragments;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AbsListView;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.drawers.AccountsListAdapter;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAccountsInterface;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 27/04/2017.
|
||||||
|
* Fragment to display content related to accounts
|
||||||
|
*/
|
||||||
|
public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccountsInterface {
|
||||||
|
|
||||||
|
|
||||||
|
private TextView noAction;
|
||||||
|
private boolean flag_loading;
|
||||||
|
private Context context;
|
||||||
|
private AsyncTask<Void, Void, Void> asyncTask;
|
||||||
|
private AccountsListAdapter accountsListAdapter;
|
||||||
|
private String max_id;
|
||||||
|
private List<Account> accounts;
|
||||||
|
private RetrieveAccountsAsyncTask.Type type;
|
||||||
|
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
|
||||||
|
private boolean firstLoad;
|
||||||
|
private SwipeRefreshLayout swipeRefreshLayout;
|
||||||
|
private int accountPerPage;
|
||||||
|
private String targetedId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
View rootView = inflater.inflate(R.layout.fragment_accounts, container, false);
|
||||||
|
|
||||||
|
context = getContext();
|
||||||
|
Bundle bundle = this.getArguments();
|
||||||
|
if (bundle != null) {
|
||||||
|
type = (RetrieveAccountsAsyncTask.Type) bundle.get("type");
|
||||||
|
targetedId = bundle.getString("targetedId", null);
|
||||||
|
}
|
||||||
|
max_id = null;
|
||||||
|
firstLoad = true;
|
||||||
|
flag_loading = true;
|
||||||
|
accounts = new ArrayList<>();
|
||||||
|
|
||||||
|
swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeContainer);
|
||||||
|
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
accountPerPage = sharedpreferences.getInt(Helper.SET_ACCOUNTS_PER_PAGE, 40);
|
||||||
|
ListView lv_accounts = (ListView) rootView.findViewById(R.id.lv_accounts);
|
||||||
|
|
||||||
|
mainLoader = (RelativeLayout) rootView.findViewById(R.id.loader);
|
||||||
|
nextElementLoader = (RelativeLayout) rootView.findViewById(R.id.loading_next_accounts);
|
||||||
|
textviewNoAction = (RelativeLayout) rootView.findViewById(R.id.no_action);
|
||||||
|
mainLoader.setVisibility(View.VISIBLE);
|
||||||
|
nextElementLoader.setVisibility(View.GONE);
|
||||||
|
accountsListAdapter = new AccountsListAdapter(context, type, this.accounts);
|
||||||
|
lv_accounts.setAdapter(accountsListAdapter);
|
||||||
|
lv_accounts.setOnScrollListener(new AbsListView.OnScrollListener() {
|
||||||
|
@Override
|
||||||
|
public void onScrollStateChanged(AbsListView view, int scrollState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||||
|
|
||||||
|
if(firstVisibleItem + visibleItemCount == totalItemCount ) {
|
||||||
|
if(!flag_loading ) {
|
||||||
|
flag_loading = true;
|
||||||
|
if( type != RetrieveAccountsAsyncTask.Type.FOLLOWERS && type != RetrieveAccountsAsyncTask.Type.FOLLOWING)
|
||||||
|
asyncTask = new RetrieveAccountsAsyncTask(context, type, max_id, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
else
|
||||||
|
asyncTask = new RetrieveAccountsAsyncTask(context, type, targetedId, max_id, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
nextElementLoader.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextElementLoader.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||||
|
@Override
|
||||||
|
public void onRefresh() {
|
||||||
|
max_id = null;
|
||||||
|
accounts = new ArrayList<>();
|
||||||
|
firstLoad = true;
|
||||||
|
flag_loading = true;
|
||||||
|
if( type != RetrieveAccountsAsyncTask.Type.FOLLOWERS && type != RetrieveAccountsAsyncTask.Type.FOLLOWING)
|
||||||
|
asyncTask = new RetrieveAccountsAsyncTask(context, type, max_id, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
else
|
||||||
|
asyncTask = new RetrieveAccountsAsyncTask(context, type, targetedId, max_id, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent,
|
||||||
|
R.color.colorPrimary,
|
||||||
|
R.color.colorPrimaryDark);
|
||||||
|
|
||||||
|
|
||||||
|
if( type != RetrieveAccountsAsyncTask.Type.FOLLOWERS && type != RetrieveAccountsAsyncTask.Type.FOLLOWING)
|
||||||
|
asyncTask = new RetrieveAccountsAsyncTask(context, type, max_id, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
else
|
||||||
|
asyncTask = new RetrieveAccountsAsyncTask(context, type, targetedId, max_id, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle saveInstance)
|
||||||
|
{
|
||||||
|
super.onCreate(saveInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
if(asyncTask != null && asyncTask.getStatus() == AsyncTask.Status.RUNNING)
|
||||||
|
asyncTask.cancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveAccounts(List<Account> accounts) {
|
||||||
|
|
||||||
|
if( firstLoad && (accounts == null || accounts.size() == 0))
|
||||||
|
textviewNoAction.setVisibility(View.VISIBLE);
|
||||||
|
else
|
||||||
|
textviewNoAction.setVisibility(View.GONE);
|
||||||
|
if( accounts != null && accounts.size() > 1)
|
||||||
|
max_id =accounts.get(accounts.size()-1).getId();
|
||||||
|
else
|
||||||
|
max_id = null;
|
||||||
|
mainLoader.setVisibility(View.GONE);
|
||||||
|
nextElementLoader.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
if( accounts != null) {
|
||||||
|
for(Account tmpAccount: accounts){
|
||||||
|
this.accounts.add(tmpAccount);
|
||||||
|
}
|
||||||
|
accountsListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
|
firstLoad = false;
|
||||||
|
if( accounts != null && accounts.size() < accountPerPage )
|
||||||
|
flag_loading = true;
|
||||||
|
else
|
||||||
|
flag_loading = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,170 @@
|
||||||
|
package fr.gouv.etalab.mastodon.fragments;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AbsListView;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.drawers.NotificationsListAdapter;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveNotificationsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveNotificationsInterface;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 28/04/2017.
|
||||||
|
* Fragment to display notifications related to accounts
|
||||||
|
*/
|
||||||
|
public class DisplayNotificationsFragment extends Fragment implements OnRetrieveNotificationsInterface {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private boolean flag_loading;
|
||||||
|
private Context context;
|
||||||
|
private AsyncTask<Void, Void, Void> asyncTask;
|
||||||
|
private NotificationsListAdapter notificationsListAdapter;
|
||||||
|
private String max_id = null;
|
||||||
|
private List<Notification> notifications;
|
||||||
|
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
|
||||||
|
private boolean firstLoad;
|
||||||
|
private SwipeRefreshLayout swipeRefreshLayout;
|
||||||
|
private int notificationPerPage;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
View rootView = inflater.inflate(R.layout.fragment_notifications, container, false);
|
||||||
|
|
||||||
|
context = getContext();
|
||||||
|
firstLoad = true;
|
||||||
|
flag_loading = true;
|
||||||
|
notifications = new ArrayList<>();
|
||||||
|
|
||||||
|
swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeContainer);
|
||||||
|
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
notificationPerPage = sharedpreferences.getInt(Helper.SET_NOTIFICATIONS_PER_PAGE, 40);
|
||||||
|
ListView lv_notifications = (ListView) rootView.findViewById(R.id.lv_notifications);
|
||||||
|
|
||||||
|
mainLoader = (RelativeLayout) rootView.findViewById(R.id.loader);
|
||||||
|
nextElementLoader = (RelativeLayout) rootView.findViewById(R.id.loading_next_notifications);
|
||||||
|
textviewNoAction = (RelativeLayout) rootView.findViewById(R.id.no_action);
|
||||||
|
mainLoader.setVisibility(View.VISIBLE);
|
||||||
|
nextElementLoader.setVisibility(View.GONE);
|
||||||
|
notificationsListAdapter = new NotificationsListAdapter(context, this.notifications);
|
||||||
|
lv_notifications.setAdapter(notificationsListAdapter);
|
||||||
|
lv_notifications.setOnScrollListener(new AbsListView.OnScrollListener() {
|
||||||
|
@Override
|
||||||
|
public void onScrollStateChanged(AbsListView view, int scrollState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||||
|
|
||||||
|
if(firstVisibleItem + visibleItemCount == totalItemCount ) {
|
||||||
|
if(!flag_loading ) {
|
||||||
|
flag_loading = true;
|
||||||
|
asyncTask = new RetrieveNotificationsAsyncTask(context, max_id, null,DisplayNotificationsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
nextElementLoader.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextElementLoader.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||||
|
@Override
|
||||||
|
public void onRefresh() {
|
||||||
|
max_id = null;
|
||||||
|
notifications = new ArrayList<>();
|
||||||
|
firstLoad = true;
|
||||||
|
flag_loading = true;
|
||||||
|
asyncTask = new RetrieveNotificationsAsyncTask(context, max_id, null,DisplayNotificationsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent,
|
||||||
|
R.color.colorPrimary,
|
||||||
|
R.color.colorPrimaryDark);
|
||||||
|
|
||||||
|
|
||||||
|
asyncTask = new RetrieveNotificationsAsyncTask(context, max_id, null, DisplayNotificationsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle saveInstance)
|
||||||
|
{
|
||||||
|
super.onCreate(saveInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
if(asyncTask != null && asyncTask.getStatus() == AsyncTask.Status.RUNNING)
|
||||||
|
asyncTask.cancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveNotifications(List<Notification> notifications, String acct) {
|
||||||
|
|
||||||
|
if( firstLoad && (notifications == null || notifications.size() == 0))
|
||||||
|
textviewNoAction.setVisibility(View.VISIBLE);
|
||||||
|
else
|
||||||
|
textviewNoAction.setVisibility(View.GONE);
|
||||||
|
if( notifications != null && notifications.size() > 1)
|
||||||
|
max_id =notifications.get(notifications.size()-1).getId();
|
||||||
|
else
|
||||||
|
max_id = null;
|
||||||
|
mainLoader.setVisibility(View.GONE);
|
||||||
|
nextElementLoader.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
if( notifications != null) {
|
||||||
|
for(Notification tmpNotification: notifications){
|
||||||
|
this.notifications.add(tmpNotification);
|
||||||
|
}
|
||||||
|
notificationsListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
|
firstLoad = false;
|
||||||
|
if( notifications != null && notifications.size() < notificationPerPage )
|
||||||
|
flag_loading = true;
|
||||||
|
else
|
||||||
|
flag_loading = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,201 @@
|
||||||
|
package fr.gouv.etalab.mastodon.fragments;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AbsListView;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.drawers.StatusListAdapter;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Status;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 24/04/2017.
|
||||||
|
* Fragment to display content related to status
|
||||||
|
*/
|
||||||
|
public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsInterface {
|
||||||
|
|
||||||
|
|
||||||
|
private TextView noAction;
|
||||||
|
private boolean flag_loading;
|
||||||
|
private Context context;
|
||||||
|
private AsyncTask<Void, Void, Void> asyncTask;
|
||||||
|
private StatusListAdapter statusListAdapter;
|
||||||
|
private String max_id;
|
||||||
|
private List<Status> statuses;
|
||||||
|
private static RetrieveFeedsAsyncTask.Type type;
|
||||||
|
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
|
||||||
|
private boolean firstLoad;
|
||||||
|
private SwipeRefreshLayout swipeRefreshLayout;
|
||||||
|
private int tootPerPage;
|
||||||
|
private String targetedId;
|
||||||
|
private String tag;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
View rootView = inflater.inflate(R.layout.fragment_status, container, false);
|
||||||
|
|
||||||
|
context = getContext();
|
||||||
|
Bundle bundle = this.getArguments();
|
||||||
|
if (bundle != null) {
|
||||||
|
type = (RetrieveFeedsAsyncTask.Type) bundle.get("type");
|
||||||
|
targetedId = bundle.getString("targetedId", null);
|
||||||
|
tag = bundle.getString("tag", null);
|
||||||
|
}
|
||||||
|
max_id = null;
|
||||||
|
flag_loading = true;
|
||||||
|
firstLoad = true;
|
||||||
|
statuses = new ArrayList<>();
|
||||||
|
boolean isOnWifi = Helper.isOnWIFI(context);
|
||||||
|
swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeContainer);
|
||||||
|
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
tootPerPage = sharedpreferences.getInt(Helper.SET_TOOTS_PER_PAGE, 40);
|
||||||
|
int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
|
||||||
|
|
||||||
|
ListView lv_status = (ListView) rootView.findViewById(R.id.lv_status);
|
||||||
|
|
||||||
|
mainLoader = (RelativeLayout) rootView.findViewById(R.id.loader);
|
||||||
|
nextElementLoader = (RelativeLayout) rootView.findViewById(R.id.loading_next_status);
|
||||||
|
textviewNoAction = (RelativeLayout) rootView.findViewById(R.id.no_action);
|
||||||
|
mainLoader.setVisibility(View.VISIBLE);
|
||||||
|
nextElementLoader.setVisibility(View.GONE);
|
||||||
|
statusListAdapter = new StatusListAdapter(context, type, isOnWifi, behaviorWithAttachments, this.statuses);
|
||||||
|
lv_status.setAdapter(statusListAdapter);
|
||||||
|
lv_status.setOnScrollListener(new AbsListView.OnScrollListener() {
|
||||||
|
@Override
|
||||||
|
public void onScrollStateChanged(AbsListView view, int scrollState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||||
|
|
||||||
|
if(firstVisibleItem + visibleItemCount == totalItemCount ) {
|
||||||
|
if(!flag_loading ) {
|
||||||
|
flag_loading = true;
|
||||||
|
if( type == RetrieveFeedsAsyncTask.Type.USER)
|
||||||
|
asyncTask = new RetrieveFeedsAsyncTask(context, type, targetedId, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
if( type == RetrieveFeedsAsyncTask.Type.TAG)
|
||||||
|
asyncTask = new RetrieveFeedsAsyncTask(context, type, tag, targetedId, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
else
|
||||||
|
asyncTask = new RetrieveFeedsAsyncTask(context, type, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
|
||||||
|
nextElementLoader.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextElementLoader.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||||
|
@Override
|
||||||
|
public void onRefresh() {
|
||||||
|
max_id = null;
|
||||||
|
statuses = new ArrayList<>();
|
||||||
|
firstLoad = true;
|
||||||
|
flag_loading = true;
|
||||||
|
if( type == RetrieveFeedsAsyncTask.Type.USER)
|
||||||
|
asyncTask = new RetrieveFeedsAsyncTask(context, type, targetedId, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
if( type == RetrieveFeedsAsyncTask.Type.TAG)
|
||||||
|
asyncTask = new RetrieveFeedsAsyncTask(context, type, tag, targetedId, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
else
|
||||||
|
asyncTask = new RetrieveFeedsAsyncTask(context, type, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent,
|
||||||
|
R.color.colorPrimary,
|
||||||
|
R.color.colorPrimaryDark);
|
||||||
|
|
||||||
|
|
||||||
|
if( type == RetrieveFeedsAsyncTask.Type.USER)
|
||||||
|
asyncTask = new RetrieveFeedsAsyncTask(context, type, targetedId, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
if( type == RetrieveFeedsAsyncTask.Type.TAG)
|
||||||
|
asyncTask = new RetrieveFeedsAsyncTask(context, type, tag, targetedId, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
else
|
||||||
|
asyncTask = new RetrieveFeedsAsyncTask(context, type, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle saveInstance)
|
||||||
|
{
|
||||||
|
super.onCreate(saveInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
if(asyncTask != null && asyncTask.getStatus() == AsyncTask.Status.RUNNING)
|
||||||
|
asyncTask.cancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveFeeds(List<Status> statuses) {
|
||||||
|
|
||||||
|
if( firstLoad && (statuses == null || statuses.size() == 0))
|
||||||
|
textviewNoAction.setVisibility(View.VISIBLE);
|
||||||
|
else
|
||||||
|
textviewNoAction.setVisibility(View.GONE);
|
||||||
|
if( statuses != null && statuses.size() > 1)
|
||||||
|
max_id =statuses.get(statuses.size()-1).getId();
|
||||||
|
else
|
||||||
|
max_id = null;
|
||||||
|
mainLoader.setVisibility(View.GONE);
|
||||||
|
nextElementLoader.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
if( statuses != null) {
|
||||||
|
for(Status tmpStatus: statuses){
|
||||||
|
this.statuses.add(tmpStatus);
|
||||||
|
}
|
||||||
|
statusListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
|
firstLoad = false;
|
||||||
|
if( statuses != null && statuses.size() < tootPerPage )
|
||||||
|
flag_loading = true;
|
||||||
|
else
|
||||||
|
flag_loading = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
package fr.gouv.etalab.mastodon.fragments;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v7.widget.SwitchCompat;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.CompoundButton;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 29/04/2017.
|
||||||
|
* Fragment for settings, yes I didn't use PreferenceFragment :)
|
||||||
|
*/
|
||||||
|
public class SettingsNotificationsFragment extends Fragment {
|
||||||
|
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
View rootView = inflater.inflate(R.layout.fragment_settings_notifications, container, false);
|
||||||
|
context = getContext();
|
||||||
|
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
|
||||||
|
boolean notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW, true);
|
||||||
|
boolean notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD, true);
|
||||||
|
boolean notif_ask = sharedpreferences.getBoolean(Helper.SET_NOTIF_ASK, true);
|
||||||
|
boolean notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION, true);
|
||||||
|
boolean notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE, true);
|
||||||
|
boolean notif_validation = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION, true);
|
||||||
|
boolean notif_wifi = sharedpreferences.getBoolean(Helper.SET_WIFI_ONLY, false);
|
||||||
|
|
||||||
|
final CheckBox set_notif_follow = (CheckBox) rootView.findViewById(R.id.set_notif_follow);
|
||||||
|
final CheckBox set_notif_follow_add = (CheckBox) rootView.findViewById(R.id.set_notif_follow_add);
|
||||||
|
final CheckBox set_notif_follow_ask = (CheckBox) rootView.findViewById(R.id.set_notif_follow_ask);
|
||||||
|
final CheckBox set_notif_follow_mention = (CheckBox) rootView.findViewById(R.id.set_notif_follow_mention);
|
||||||
|
final CheckBox set_notif_follow_share = (CheckBox) rootView.findViewById(R.id.set_notif_follow_share);
|
||||||
|
final CheckBox set_share_validation = (CheckBox) rootView.findViewById(R.id.set_share_validation);
|
||||||
|
final SwitchCompat switchCompatWIFI = (SwitchCompat) rootView.findViewById(R.id.set_wifi_only);
|
||||||
|
|
||||||
|
set_notif_follow.setChecked(notif_follow);
|
||||||
|
set_notif_follow_add.setChecked(notif_add);
|
||||||
|
set_notif_follow_ask.setChecked(notif_ask);
|
||||||
|
set_notif_follow_mention.setChecked(notif_mention);
|
||||||
|
set_notif_follow_share.setChecked(notif_share);
|
||||||
|
set_share_validation.setChecked(notif_validation);
|
||||||
|
switchCompatWIFI.setChecked(notif_wifi);
|
||||||
|
|
||||||
|
|
||||||
|
set_notif_follow.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putBoolean(Helper.SET_NOTIF_FOLLOW, set_notif_follow.isChecked());
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
set_notif_follow_add.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putBoolean(Helper.SET_NOTIF_ADD, set_notif_follow_add.isChecked());
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
set_notif_follow_ask.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putBoolean(Helper.SET_NOTIF_ASK, set_notif_follow_ask.isChecked());
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
set_notif_follow_mention.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putBoolean(Helper.SET_NOTIF_MENTION, set_notif_follow_mention.isChecked());
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
set_notif_follow_share.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putBoolean(Helper.SET_NOTIF_SHARE, set_notif_follow_share.isChecked());
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
set_share_validation.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putBoolean(Helper.SET_NOTIF_VALIDATION, set_share_validation.isChecked());
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
switchCompatWIFI.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
// Save the state here
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putBoolean(Helper.SET_WIFI_ONLY, isChecked);
|
||||||
|
editor.apply();
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle saveInstance) {
|
||||||
|
super.onCreate(saveInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,172 @@
|
||||||
|
package fr.gouv.etalab.mastodon.fragments;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.RadioGroup;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 25/04/2017.
|
||||||
|
* Fragment for settings, yes I didn't use PreferenceFragment :)
|
||||||
|
*/
|
||||||
|
public class SettingsOptimizationFragment extends Fragment {
|
||||||
|
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
View rootView = inflater.inflate(R.layout.fragment_settings_optimization, container, false);
|
||||||
|
context = getContext();
|
||||||
|
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
|
||||||
|
|
||||||
|
//Status per page
|
||||||
|
SeekBar statusSeekBar = (SeekBar) rootView.findViewById(R.id.set_toots_per_page);
|
||||||
|
final TextView set_toots_page_value = (TextView) rootView.findViewById(R.id.set_toots_page_value);
|
||||||
|
statusSeekBar.setMax(30);
|
||||||
|
int tootPerPage = sharedpreferences.getInt(Helper.SET_TOOTS_PER_PAGE, 40);
|
||||||
|
statusSeekBar.setProgress(tootPerPage-10);
|
||||||
|
set_toots_page_value.setText(String.valueOf(tootPerPage));
|
||||||
|
statusSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch(SeekBar seekBar) {}
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch(SeekBar seekBar) {}
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
|
int value = 10 + progress;
|
||||||
|
set_toots_page_value.setText(String.valueOf(value));
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putInt(Helper.SET_TOOTS_PER_PAGE, value);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Accounts per page
|
||||||
|
SeekBar accountsSeekBar = (SeekBar) rootView.findViewById(R.id.set_accounts_per_page);
|
||||||
|
final TextView set_accounts_page_value = (TextView) rootView.findViewById(R.id.set_accounts_page_value);
|
||||||
|
accountsSeekBar.setMax(30);
|
||||||
|
int accountsPerPage = sharedpreferences.getInt(Helper.SET_ACCOUNTS_PER_PAGE, 40);
|
||||||
|
accountsSeekBar.setProgress(accountsPerPage-10);
|
||||||
|
set_accounts_page_value.setText(String.valueOf(accountsPerPage));
|
||||||
|
accountsSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch(SeekBar seekBar) {}
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch(SeekBar seekBar) {}
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
|
int value = 10 + progress;
|
||||||
|
set_accounts_page_value.setText(String.valueOf(value));
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putInt(Helper.SET_ACCOUNTS_PER_PAGE, value);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//Notifications per page
|
||||||
|
SeekBar notificationsSeekBar = (SeekBar) rootView.findViewById(R.id.set_notifications_per_page);
|
||||||
|
final TextView set_notifications_page_value = (TextView) rootView.findViewById(R.id.set_notifications_page_value);
|
||||||
|
notificationsSeekBar.setMax(30);
|
||||||
|
int notificationsPerPage = sharedpreferences.getInt(Helper.SET_NOTIFICATIONS_PER_PAGE, 40);
|
||||||
|
notificationsSeekBar.setProgress(notificationsPerPage-10);
|
||||||
|
set_notifications_page_value.setText(String.valueOf(notificationsPerPage));
|
||||||
|
notificationsSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch(SeekBar seekBar) {}
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch(SeekBar seekBar) {}
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
|
int value = 10 + progress;
|
||||||
|
set_notifications_page_value.setText(String.valueOf(value));
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putInt(Helper.SET_NOTIFICATIONS_PER_PAGE, value);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Manage download of attachments
|
||||||
|
RadioGroup radioGroup = (RadioGroup) rootView.findViewById(R.id.set_attachment_group);
|
||||||
|
int attachmentAction = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
|
||||||
|
switch (attachmentAction){
|
||||||
|
case Helper.ATTACHMENT_ALWAYS:
|
||||||
|
radioGroup.check(R.id.set_attachment_always);
|
||||||
|
break;
|
||||||
|
case Helper.ATTACHMENT_WIFI:
|
||||||
|
radioGroup.check(R.id.set_attachment_wifi);
|
||||||
|
break;
|
||||||
|
case Helper.ATTACHMENT_ASK:
|
||||||
|
radioGroup.check(R.id.set_attachment_ask);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||||
|
switch(checkedId) {
|
||||||
|
case R.id.set_attachment_always:
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
|
||||||
|
editor.apply();
|
||||||
|
break;
|
||||||
|
case R.id.set_attachment_wifi:
|
||||||
|
editor = sharedpreferences.edit();
|
||||||
|
editor.putInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_WIFI);
|
||||||
|
editor.apply();
|
||||||
|
break;
|
||||||
|
case R.id.set_attachment_ask:
|
||||||
|
editor = sharedpreferences.edit();
|
||||||
|
editor.putInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ASK);
|
||||||
|
editor.apply();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle saveInstance) {
|
||||||
|
super.onCreate(saveInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package fr.gouv.etalab.mastodon.fragments;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.design.widget.TabLayout;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 29/04/2017.
|
||||||
|
* Tablayout selection for settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TabLayoutSettingsFragment extends Fragment {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
View inflatedView = inflater.inflate(R.layout.tablayout_settings, container, false);
|
||||||
|
|
||||||
|
TabLayout tabLayout = (TabLayout) inflatedView.findViewById(R.id.tabLayout);
|
||||||
|
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.notifications)));
|
||||||
|
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.optimization)));
|
||||||
|
final ViewPager viewPager = (ViewPager) inflatedView.findViewById(R.id.viewpager);
|
||||||
|
|
||||||
|
viewPager.setAdapter(new PagerAdapter
|
||||||
|
(getChildFragmentManager(), tabLayout.getTabCount()));
|
||||||
|
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
|
||||||
|
|
||||||
|
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onTabSelected(TabLayout.Tab tab) {
|
||||||
|
viewPager.setCurrentItem(tab.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTabUnselected(TabLayout.Tab tab) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTabReselected(TabLayout.Tab tab) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return inflatedView;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page Adapter for settings
|
||||||
|
*/
|
||||||
|
private class PagerAdapter extends FragmentStatePagerAdapter {
|
||||||
|
int mNumOfTabs;
|
||||||
|
|
||||||
|
private PagerAdapter(FragmentManager fm, int NumOfTabs) {
|
||||||
|
super(fm);
|
||||||
|
this.mNumOfTabs = NumOfTabs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fragment getItem(int position) {
|
||||||
|
switch (position) {
|
||||||
|
case 0:
|
||||||
|
return new SettingsNotificationsFragment();
|
||||||
|
case 1:
|
||||||
|
return new SettingsOptimizationFragment();
|
||||||
|
default:
|
||||||
|
return new SettingsNotificationsFragment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return mNumOfTabs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,359 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
|
||||||
|
package fr.gouv.etalab.mastodon.helper;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.DownloadManager;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
|
||||||
|
import static android.content.Context.DOWNLOAD_SERVICE;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
* - Constants are defined here.
|
||||||
|
* - Reusable methods are implemented in this section
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Helper {
|
||||||
|
|
||||||
|
|
||||||
|
public static final String TAG = "mastodon_etalab";
|
||||||
|
//Connection with API
|
||||||
|
public static final String OAUTH_SCHEME = "oauth2redirect";
|
||||||
|
public static final String OAUTH_REDIRECT_HOST = "fr.gouv.etalab.mastodon";
|
||||||
|
public static final String INSTANCE = "mastodon.etalab.gouv.fr";
|
||||||
|
public static final String OAUTH_SCOPES = "read write follow";
|
||||||
|
public static final String PREF_KEY_OAUTH_TOKEN = "oauth_token";
|
||||||
|
public static final String PREF_KEY_ID = "userID";
|
||||||
|
public static final String REDIRECT_CONTENT = "/redirect_mastodon_api";
|
||||||
|
public static final int EXTERNAL_STORAGE_REQUEST_CODE = 84;
|
||||||
|
|
||||||
|
//Some definitions
|
||||||
|
public static final String CLIENT_NAME = "client_name";
|
||||||
|
public static final String APP_PREFS = "app_prefs";
|
||||||
|
public static final String ID = "id";
|
||||||
|
public static final String CLIENT_ID = "client_id";
|
||||||
|
public static final String CLIENT_SECRET = "client_secret";
|
||||||
|
public static final String REDIRECT_URI = "redirect_uri";
|
||||||
|
public static final String REDIRECT_URIS = "redirect_uris";
|
||||||
|
public static final String RESPONSE_TYPE = "response_type";
|
||||||
|
public static final String SCOPE = "scope";
|
||||||
|
public static final String SCOPES = "scopes";
|
||||||
|
public static final String WEBSITE = "website";
|
||||||
|
public static final String LAST_NOTIFICATION_MAX_ID = "last_notification_max_id";
|
||||||
|
|
||||||
|
//Notifications
|
||||||
|
public static final String NOTIFICATION_TYPE = "notification_type";
|
||||||
|
public static final int NOTIFICATION_INTENT = 1;
|
||||||
|
|
||||||
|
//Settings
|
||||||
|
public static final String SET_TOOTS_PER_PAGE = "set_toots_per_page";
|
||||||
|
public static final String SET_ACCOUNTS_PER_PAGE = "set_accounts_per_page";
|
||||||
|
public static final String SET_NOTIFICATIONS_PER_PAGE = "set_notifications_per_page";
|
||||||
|
public static final String SET_ATTACHMENT_ACTION = "set_attachment_action";
|
||||||
|
public static final int ATTACHMENT_ALWAYS = 1;
|
||||||
|
public static final int ATTACHMENT_WIFI = 2;
|
||||||
|
public static final int ATTACHMENT_ASK = 3;
|
||||||
|
|
||||||
|
|
||||||
|
public static final String SET_NOTIF_FOLLOW = "set_notif_follow";
|
||||||
|
public static final String SET_NOTIF_ADD = "set_notif_follow_add";
|
||||||
|
public static final String SET_NOTIF_ASK = "set_notif_follow_ask";
|
||||||
|
public static final String SET_NOTIF_MENTION = "set_notif_follow_mention";
|
||||||
|
public static final String SET_NOTIF_SHARE = "set_notif_follow_share";
|
||||||
|
public static final String SET_NOTIF_VALIDATION = "set_share_validation";
|
||||||
|
public static final String SET_WIFI_ONLY = "set_wifi_only";
|
||||||
|
public static final String SET_NOTIF_SILENT = "set_notif_silent";
|
||||||
|
|
||||||
|
//End points
|
||||||
|
public static final String EP_AUTHORIZE = "/oauth/authorize";
|
||||||
|
|
||||||
|
|
||||||
|
//Refresh job
|
||||||
|
public static final int MINUTES_BETWEEN_NOTIFICATIONS_REFRESH = 15;
|
||||||
|
|
||||||
|
//Intent
|
||||||
|
public static final String INTENT_ACTION = "intent_action";
|
||||||
|
public static final int INTENT_NOTIFICATION = 1;
|
||||||
|
|
||||||
|
//Receiver
|
||||||
|
public static final String SEARCH_VALIDATE_ACCOUNT = "search_validate_account";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Check if the user is connected to Internet
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static boolean isConnectingToInternet(Context context) {
|
||||||
|
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
NetworkInfo ni = cm.getActiveNetworkInfo();
|
||||||
|
if ( ni != null && ni.isConnected()) {
|
||||||
|
try {
|
||||||
|
//Google is used for the ping
|
||||||
|
InetAddress ipAddr = InetAddress.getByName("google.com");
|
||||||
|
return !ipAddr.toString().equals("");
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns boolean depending if the user is authenticated
|
||||||
|
* @param context Context
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static boolean isLoggedIn(Context context) {
|
||||||
|
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
String prefKeyOauthTokenT = sharedpreferences.getString(PREF_KEY_OAUTH_TOKEN, null);
|
||||||
|
return ( prefKeyOauthTokenT != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log out the authenticated user by removing its token
|
||||||
|
* @param context Context
|
||||||
|
*/
|
||||||
|
public static void logout(Context context) {
|
||||||
|
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, null);
|
||||||
|
editor.putString(Helper.CLIENT_ID, null);
|
||||||
|
editor.putString(Helper.CLIENT_SECRET, null);
|
||||||
|
editor.putString(Helper.PREF_KEY_ID, null);
|
||||||
|
editor.putString(Helper.ID, null);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert String date from Mastodon
|
||||||
|
* @param context Context
|
||||||
|
* @param date String
|
||||||
|
* @return Date
|
||||||
|
*/
|
||||||
|
public static Date mstStringToDate(Context context, String date){
|
||||||
|
Locale userLocale;
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
userLocale = context.getResources().getConfiguration().getLocales().get(0);
|
||||||
|
} else {
|
||||||
|
//noinspection deprecation
|
||||||
|
userLocale = context.getResources().getConfiguration().locale;
|
||||||
|
}
|
||||||
|
final String STRING_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
|
||||||
|
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(STRING_DATE_FORMAT, userLocale);
|
||||||
|
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("gmt"));
|
||||||
|
simpleDateFormat.setLenient(true);
|
||||||
|
try {
|
||||||
|
return simpleDateFormat.parse(date);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a date in String -> format yyyy-MM-dd HH:mm:ss
|
||||||
|
* @param context Context
|
||||||
|
* @param date Date
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String dateToString(Context context, Date date) {
|
||||||
|
Locale userLocale;
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
userLocale = context.getResources().getConfiguration().getLocales().get(0);
|
||||||
|
} else {
|
||||||
|
//noinspection deprecation
|
||||||
|
userLocale = context.getResources().getConfiguration().locale;
|
||||||
|
}
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",userLocale);
|
||||||
|
return dateFormat.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert String date from db to Date Object
|
||||||
|
* @param stringDate date to convert
|
||||||
|
* @return Date
|
||||||
|
*/
|
||||||
|
public static Date stringToDate(Context context, String stringDate) {
|
||||||
|
if( stringDate == null)
|
||||||
|
return null;
|
||||||
|
Locale userLocale;
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
userLocale = context.getResources().getConfiguration().getLocales().get(0);
|
||||||
|
} else {
|
||||||
|
//noinspection deprecation
|
||||||
|
userLocale = context.getResources().getConfiguration().locale;
|
||||||
|
}
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",userLocale);
|
||||||
|
Date date = null;
|
||||||
|
try {
|
||||||
|
date = dateFormat.parse(stringDate);
|
||||||
|
} catch (java.text.ParseException ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if WIFI is opened
|
||||||
|
* @param context Context
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static boolean isOnWIFI(Context context) {
|
||||||
|
ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
NetworkInfo activeNetwork = connManager.getActiveNetworkInfo();
|
||||||
|
return (activeNetwork != null && activeNetwork.getType() == ConnectivityManager.TYPE_WIFI);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Returns a String depending of the date
|
||||||
|
* @param context Context
|
||||||
|
* @param dateToot Date
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String dateDiff(Context context, Date dateToot){
|
||||||
|
Date now = new Date();
|
||||||
|
long diff = now.getTime() - dateToot.getTime();
|
||||||
|
long seconds = diff / 1000;
|
||||||
|
long minutes = seconds / 60;
|
||||||
|
long hours = minutes / 60;
|
||||||
|
long days = hours / 24;
|
||||||
|
long months = days / 30;
|
||||||
|
long years = days / 365;
|
||||||
|
|
||||||
|
if( years > 0)
|
||||||
|
return context.getResources().getQuantityString(R.plurals.date_year, (int)years, (int)years);
|
||||||
|
else if( months > 0)
|
||||||
|
return context.getResources().getQuantityString(R.plurals.date_month, (int)months, (int)months);
|
||||||
|
else if( days > 2)
|
||||||
|
return context.getString(R.string.date_day,days);
|
||||||
|
else if(days == 2 )
|
||||||
|
return context.getString(R.string.date_day_before_yesterday);
|
||||||
|
else if(days == 1 )
|
||||||
|
return context.getString(R.string.date_yesterday);
|
||||||
|
else if(hours > 0)
|
||||||
|
return context.getResources().getQuantityString(R.plurals.date_hours, (int)hours, (int)hours);
|
||||||
|
else if(minutes > 0)
|
||||||
|
return context.getResources().getQuantityString(R.plurals.date_minutes, (int)minutes, (int)minutes);
|
||||||
|
else
|
||||||
|
return context.getResources().getQuantityString(R.plurals.date_seconds, (int)seconds, (int)seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Toast message depending of the status code and the initial action
|
||||||
|
* @param context Context
|
||||||
|
* @param statusCode int the status code
|
||||||
|
* @param statusAction API.StatusAction the initial action
|
||||||
|
*/
|
||||||
|
public static void manageMessageStatusCode(Context context, int statusCode,API.StatusAction statusAction){
|
||||||
|
String message = "";
|
||||||
|
if( statusCode == 200){
|
||||||
|
if( statusAction == API.StatusAction.BLOCK){
|
||||||
|
message = context.getString(R.string.toast_block);
|
||||||
|
}else if(statusAction == API.StatusAction.UNBLOCK){
|
||||||
|
message = context.getString(R.string.toast_unblock);
|
||||||
|
}else if(statusAction == API.StatusAction.REBLOG){
|
||||||
|
message = context.getString(R.string.toast_reblog);
|
||||||
|
}else if(statusAction == API.StatusAction.UNREBLOG){
|
||||||
|
message = context.getString(R.string.toast_unreblog);
|
||||||
|
}else if(statusAction == API.StatusAction.MUTE){
|
||||||
|
message = context.getString(R.string.toast_mute);
|
||||||
|
}else if(statusAction == API.StatusAction.UNMUTE){
|
||||||
|
message = context.getString(R.string.toast_unmute);
|
||||||
|
}else if(statusAction == API.StatusAction.FOLLOW){
|
||||||
|
message = context.getString(R.string.toast_follow);
|
||||||
|
}else if(statusAction == API.StatusAction.UNFOLLOW){
|
||||||
|
message = context.getString(R.string.toast_unfollow);
|
||||||
|
}else if(statusAction == API.StatusAction.FAVOURITE){
|
||||||
|
message = context.getString(R.string.toast_favourite);
|
||||||
|
}else if(statusAction == API.StatusAction.UNFAVOURITE){
|
||||||
|
message = context.getString(R.string.toast_unfavourite);
|
||||||
|
}else if(statusAction == API.StatusAction.REPORT){
|
||||||
|
message = context.getString(R.string.toast_report);
|
||||||
|
}else if(statusAction == API.StatusAction.UNSTATUS){
|
||||||
|
message = context.getString(R.string.toast_unstatus);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
message = context.getString(R.string.toast_error);
|
||||||
|
}
|
||||||
|
if( !message.trim().equals(""))
|
||||||
|
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void manageDownloads(final Context context, final String url){
|
||||||
|
|
||||||
|
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
|
||||||
|
final DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
|
||||||
|
Uri uri = Uri.parse(url);
|
||||||
|
File f = new File("" + uri);
|
||||||
|
final String fileName = f.getName();
|
||||||
|
builder.setMessage(context.getResources().getString(R.string.download_file, fileName));
|
||||||
|
builder.setCancelable(false)
|
||||||
|
.setPositiveButton(context.getString(R.string.yes), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
request.allowScanningByMediaScanner();
|
||||||
|
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,fileName);
|
||||||
|
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||||
|
DownloadManager dm = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
|
||||||
|
dm.enqueue(request);
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.setNegativeButton(context.getString(R.string.cancel), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AlertDialog alert = builder.create();
|
||||||
|
if( alert.getWindow() != null )
|
||||||
|
alert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
||||||
|
alert.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 29/04/2017.
|
||||||
|
* Interface when post actions has been done with a status
|
||||||
|
*/
|
||||||
|
public interface OnPostActionInterface {
|
||||||
|
void onPostAction(int statusCode, API.StatusAction statusAction, String userId);
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 01/05/2017.
|
||||||
|
* Interface when one account have been retrieved
|
||||||
|
*/
|
||||||
|
public interface OnRetrieveAccountInterface {
|
||||||
|
void onRetrieveAccount(Account account);
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 27/04/2017.
|
||||||
|
* Interface when accounts have been retrieved
|
||||||
|
*/
|
||||||
|
public interface OnRetrieveAccountsInterface {
|
||||||
|
void onRetrieveAccounts(List<Account> accounts);
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Attachment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 01/05/2017.
|
||||||
|
* Interface when an attachment has been retrieved
|
||||||
|
*/
|
||||||
|
public interface OnRetrieveAttachmentInterface {
|
||||||
|
void onRetrieveAttachment(Attachment attachment);
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 04/05/2017.
|
||||||
|
* Interface when a context for a status has been retrieved
|
||||||
|
*/
|
||||||
|
public interface OnRetrieveContextInterface {
|
||||||
|
void onRetrieveFeeds(Context context);
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 01/05/2017.
|
||||||
|
* Interface when status have been retrieved for an account
|
||||||
|
*/
|
||||||
|
public interface OnRetrieveFeedsAccountInterface {
|
||||||
|
void onRetrieveFeedsAccount(List<Status> statuses);
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 24/04/2017.
|
||||||
|
* Interface when status have been retrieved
|
||||||
|
*/
|
||||||
|
public interface OnRetrieveFeedsInterface {
|
||||||
|
void onRetrieveFeeds(List<Status> statuses);
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 28/04/2017.
|
||||||
|
* Interface when notifications have been retrieved
|
||||||
|
*/
|
||||||
|
public interface OnRetrieveNotificationsInterface {
|
||||||
|
void onRetrieveNotifications(List<Notification> notifications, String acct);
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Relationship;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 01/05/2017.
|
||||||
|
* Interface when relationship has been retrieved for an account
|
||||||
|
*/
|
||||||
|
public interface OnRetrieveRelationshipInterface {
|
||||||
|
void onRetrieveRelationship(Relationship relationship);
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Results;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 05/05/2017.
|
||||||
|
* Interface for search
|
||||||
|
*/
|
||||||
|
public interface OnRetrieveSearchInterface {
|
||||||
|
void onRetrieveSearch(Results results);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 03/05/2017.
|
||||||
|
* Interface when account is updated
|
||||||
|
*/
|
||||||
|
public interface OnUpdateAccountInfoInterface {
|
||||||
|
void onUpdateAccountInfo(boolean error);
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package fr.gouv.etalab.mastodon.jobs;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
import com.evernote.android.job.Job;
|
||||||
|
import com.evernote.android.job.JobCreator;
|
||||||
|
import com.evernote.android.job.JobManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 29/04/2017.
|
||||||
|
* Notification job
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ApplicationJob implements JobCreator {
|
||||||
|
@Override
|
||||||
|
public Job create(String tag) {
|
||||||
|
switch (tag) {
|
||||||
|
case NotificationsSyncJob.NOTIFICATION_REFRESH:
|
||||||
|
return new NotificationsSyncJob();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cancelAllJob(String TAG){
|
||||||
|
JobManager.instance().cancelAllForTag(TAG);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,251 @@
|
||||||
|
package fr.gouv.etalab.mastodon.jobs;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.media.RingtoneManager;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v4.app.NotificationCompat;
|
||||||
|
import android.support.v4.app.NotificationManagerCompat;
|
||||||
|
|
||||||
|
import com.evernote.android.job.Job;
|
||||||
|
import com.evernote.android.job.JobManager;
|
||||||
|
import com.evernote.android.job.JobRequest;
|
||||||
|
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.activities.MainActivity;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import mastodon.etalab.gouv.fr.mastodon.R;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveNotificationsAsyncTask;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveNotificationsInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
|
||||||
|
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
|
||||||
|
|
||||||
|
import static fr.gouv.etalab.mastodon.helper.Helper.INTENT_ACTION;
|
||||||
|
import static fr.gouv.etalab.mastodon.helper.Helper.INTENT_NOTIFICATION;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 29/04/2017.
|
||||||
|
* Notifications refresh job
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class NotificationsSyncJob extends Job implements OnRetrieveNotificationsInterface{
|
||||||
|
|
||||||
|
public static final String NOTIFICATION_REFRESH = "job_notification";
|
||||||
|
private int jobId;
|
||||||
|
private int notificationId;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
protected Result onRunJob(Params params) {
|
||||||
|
//Code refresh here
|
||||||
|
callAsynchronousTask();
|
||||||
|
return Result.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static int schedule(Context context, boolean updateCurrent){
|
||||||
|
|
||||||
|
Set<JobRequest> jobRequests = JobManager.instance().getAllJobRequestsForTag(NOTIFICATION_REFRESH);
|
||||||
|
if (!jobRequests.isEmpty() && !updateCurrent) {
|
||||||
|
return jobRequests.iterator().next().getJobId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JobRequest.Builder(NotificationsSyncJob.NOTIFICATION_REFRESH)
|
||||||
|
.setPeriodic(TimeUnit.MINUTES.toMillis(Helper.MINUTES_BETWEEN_NOTIFICATIONS_REFRESH), TimeUnit.MINUTES.toMillis(5))
|
||||||
|
.setPersisted(true)
|
||||||
|
.setUpdateCurrent(updateCurrent)
|
||||||
|
.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
|
||||||
|
.setRequirementsEnforced(false)
|
||||||
|
.build()
|
||||||
|
.schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task in background starts here.
|
||||||
|
*/
|
||||||
|
private void callAsynchronousTask() {
|
||||||
|
SQLiteDatabase db = Sqlite.getInstance(getContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||||
|
//If an Internet connection and user agrees with notification refresh
|
||||||
|
final SharedPreferences sharedpreferences = getContext().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
//If WIFI only and on WIFI OR user defined any connections to use the service.
|
||||||
|
if(!sharedpreferences.getBoolean(Helper.SET_WIFI_ONLY, false) || Helper.isOnWIFI(getContext())) {
|
||||||
|
List<Account> accounts = new AccountDAO(getContext(),db).getAllAccount();
|
||||||
|
//It means there is no user in DB.
|
||||||
|
if( accounts == null )
|
||||||
|
return;
|
||||||
|
//Retrieve users in db that owner has.
|
||||||
|
for (Account account: accounts) {
|
||||||
|
String max_id = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + account.getAcct(), null);
|
||||||
|
notificationId = (int) Math.round(Double.parseDouble(account.getId())/1000);
|
||||||
|
new RetrieveNotificationsAsyncTask(getContext(), max_id, account.getAcct(), NotificationsSyncJob.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveNotifications(List<Notification> notifications, String acct) {
|
||||||
|
if( notifications == null || notifications.size() == 0)
|
||||||
|
return;
|
||||||
|
Bitmap icon_notification = null;
|
||||||
|
final SharedPreferences sharedpreferences = getContext().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
boolean notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW, true);
|
||||||
|
boolean notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD, true);
|
||||||
|
boolean notif_ask = sharedpreferences.getBoolean(Helper.SET_NOTIF_ASK, true);
|
||||||
|
boolean notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION, true);
|
||||||
|
boolean notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE, true);
|
||||||
|
String max_id = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + acct, null);
|
||||||
|
//No previous notifications in cache, so no notification will be sent
|
||||||
|
if( max_id != null ){
|
||||||
|
int newFollows = 0;
|
||||||
|
int newAdds = 0;
|
||||||
|
int newAsks = 0;
|
||||||
|
int newMentions = 0;
|
||||||
|
int newShare = 0;
|
||||||
|
String notificationUrl = null;
|
||||||
|
String title = null;
|
||||||
|
String message = null;
|
||||||
|
for(Notification notification: notifications){
|
||||||
|
//The notification associated to max_id is discarded as it is supposed to have already been sent
|
||||||
|
if( notification.getId().equals(max_id))
|
||||||
|
continue;
|
||||||
|
switch (notification.getType()){
|
||||||
|
case "mention":
|
||||||
|
if(notif_mention){
|
||||||
|
newMentions++;
|
||||||
|
if( notificationUrl == null){
|
||||||
|
notificationUrl = notification.getAccount().getAvatar();
|
||||||
|
title = String.format("@%s %s", notification.getAccount().getAcct(),getContext().getString(R.string.notif_mention));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "reblog":
|
||||||
|
if(notif_share){
|
||||||
|
newShare++;
|
||||||
|
if( notificationUrl == null){
|
||||||
|
notificationUrl = notification.getAccount().getAvatar();
|
||||||
|
title = String.format("@%s %s", notification.getAccount().getAcct(),getContext().getString(R.string.notif_reblog));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "favourite":
|
||||||
|
if(notif_add){
|
||||||
|
newAdds++;
|
||||||
|
if( notificationUrl == null){
|
||||||
|
notificationUrl = notification.getAccount().getAvatar();
|
||||||
|
title = String.format("@%s %s", notification.getAccount().getAcct(),getContext().getString(R.string.notif_favourite));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "follow":
|
||||||
|
if(notif_follow){
|
||||||
|
newFollows++;
|
||||||
|
if( notificationUrl == null){
|
||||||
|
notificationUrl = notification.getAccount().getAvatar();
|
||||||
|
title = String.format("@%s %s", notification.getAccount().getAcct(),getContext().getString(R.string.notif_follow));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
if( notificationUrl != null && icon_notification == null){
|
||||||
|
try {
|
||||||
|
ImageLoader imageLoaderNoty = ImageLoader.getInstance();
|
||||||
|
File cacheDir = new File(getContext().getCacheDir(), getContext().getString(R.string.app_name));
|
||||||
|
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getContext())
|
||||||
|
.threadPoolSize(5)
|
||||||
|
.threadPriority(Thread.MIN_PRIORITY + 3)
|
||||||
|
.denyCacheImageMultipleSizesInMemory()
|
||||||
|
.diskCache(new UnlimitedDiskCache(cacheDir))
|
||||||
|
.build();
|
||||||
|
imageLoaderNoty.init(config);
|
||||||
|
icon_notification = imageLoaderNoty.loadImageSync(notificationUrl);
|
||||||
|
}catch (Exception e){
|
||||||
|
icon_notification = BitmapFactory.decodeResource(getContext().getResources(),
|
||||||
|
R.drawable.mastodon_logo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int allNotifCount = newFollows + newAdds + newAsks + newMentions + newShare;
|
||||||
|
if( allNotifCount > 0){
|
||||||
|
//Some others notification
|
||||||
|
int other = allNotifCount -1;
|
||||||
|
if(other > 0 )
|
||||||
|
message = getContext().getResources().getQuantityString(R.plurals.other_notifications, other, other);
|
||||||
|
else
|
||||||
|
message = "";
|
||||||
|
notify_user(icon_notification,title,message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + acct, notifications.get(0).getId());
|
||||||
|
editor.apply();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends notification with intent
|
||||||
|
* @param icon Bitmap profile picture
|
||||||
|
* @param title String title of the notification
|
||||||
|
* @param message String message for the notification
|
||||||
|
*/
|
||||||
|
private void notify_user(Bitmap icon, String title, String message ) {
|
||||||
|
final SharedPreferences sharedpreferences = getContext().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
// prepare intent which is triggered if the user click on the notification
|
||||||
|
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getContext());
|
||||||
|
final Intent intent = new Intent(getContext(), MainActivity.class);
|
||||||
|
intent.putExtra(Helper.NOTIFICATION_TYPE, Helper.NOTIFICATION_INTENT);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
|
||||||
|
intent.putExtra(INTENT_ACTION, INTENT_NOTIFICATION);
|
||||||
|
PendingIntent pIntent = PendingIntent.getActivity(getContext(), notificationId, intent, PendingIntent.FLAG_ONE_SHOT);
|
||||||
|
|
||||||
|
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||||
|
// build notification
|
||||||
|
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getContext())
|
||||||
|
.setSmallIcon(R.drawable.notification_icon)
|
||||||
|
.setTicker(message)
|
||||||
|
.setWhen(System.currentTimeMillis())
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setContentIntent(pIntent)
|
||||||
|
.setContentText(message);
|
||||||
|
if( !sharedpreferences.getBoolean(Helper.SET_NOTIF_SILENT,false) ) {
|
||||||
|
notificationBuilder.setDefaults(-1);
|
||||||
|
}
|
||||||
|
notificationBuilder.setContentTitle(title);
|
||||||
|
notificationBuilder.setLargeIcon(icon);
|
||||||
|
notificationManager.notify(notificationId, notificationBuilder.build());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,261 @@
|
||||||
|
package fr.gouv.etalab.mastodon.sqlite;
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 24/04/2017.
|
||||||
|
* Manage Account in DB
|
||||||
|
*/
|
||||||
|
public class AccountDAO {
|
||||||
|
|
||||||
|
private SQLiteDatabase db;
|
||||||
|
public Context context;
|
||||||
|
|
||||||
|
|
||||||
|
public AccountDAO(Context context, SQLiteDatabase db) {
|
||||||
|
//Creation of the DB with tables
|
||||||
|
this.context = context;
|
||||||
|
this.db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert an Account in database
|
||||||
|
* @param account Account
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean insertAccount(Account account)
|
||||||
|
{
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
|
||||||
|
values.put(Sqlite.COL_USER_ID, account.getId());
|
||||||
|
values.put(Sqlite.COL_USERNAME, account.getUsername());
|
||||||
|
values.put(Sqlite.COL_ACCT, account.getAcct());
|
||||||
|
values.put(Sqlite.COL_DISPLAYED_NAME, account.getDisplay_name());
|
||||||
|
values.put(Sqlite.COL_LOCKED,account.isLocked());
|
||||||
|
values.put(Sqlite.COL_FOLLOWERS_COUNT,account.getFollowers_count());
|
||||||
|
values.put(Sqlite.COL_FOLLOWING_COUNT,account.getFollowing_count());
|
||||||
|
values.put(Sqlite.COL_STATUSES_COUNT,account.getStatuses_count());
|
||||||
|
values.put(Sqlite.COL_NOTE,account.getNote());
|
||||||
|
values.put(Sqlite.COL_URL,account.getUrl());
|
||||||
|
values.put(Sqlite.COL_AVATAR,account.getAvatar());
|
||||||
|
values.put(Sqlite.COL_AVATAR_STATIC,account.getAvatar_static());
|
||||||
|
values.put(Sqlite.COL_HEADER,account.getHeader());
|
||||||
|
values.put(Sqlite.COL_HEADER_STATIC,account.getHeader_static());
|
||||||
|
values.put(Sqlite.COL_CREATED_AT, Helper.dateToString(context, account.getCreated_at()));
|
||||||
|
values.put(Sqlite.COL_INSTANCE, account.getInstance());
|
||||||
|
if( account.getToken() != null)
|
||||||
|
values.put(Sqlite.COL_OAUTHTOKEN, account.getToken());
|
||||||
|
|
||||||
|
//Inserts account
|
||||||
|
try{
|
||||||
|
db.insert(Sqlite.TABLE_USER_ACCOUNT, null, values);
|
||||||
|
|
||||||
|
}catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update an Account in database
|
||||||
|
* @param account Account
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public int updateAccount(Account account)
|
||||||
|
{
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
|
||||||
|
values.put(Sqlite.COL_ACCT, account.getAcct());
|
||||||
|
values.put(Sqlite.COL_DISPLAYED_NAME, account.getDisplay_name());
|
||||||
|
values.put(Sqlite.COL_LOCKED,account.isLocked());
|
||||||
|
values.put(Sqlite.COL_FOLLOWERS_COUNT,account.getFollowers_count());
|
||||||
|
values.put(Sqlite.COL_FOLLOWING_COUNT,account.getFollowing_count());
|
||||||
|
values.put(Sqlite.COL_STATUSES_COUNT,account.getStatuses_count());
|
||||||
|
values.put(Sqlite.COL_NOTE,account.getNote());
|
||||||
|
values.put(Sqlite.COL_URL,account.getUrl());
|
||||||
|
values.put(Sqlite.COL_AVATAR,account.getAvatar());
|
||||||
|
values.put(Sqlite.COL_AVATAR_STATIC,account.getAvatar_static());
|
||||||
|
values.put(Sqlite.COL_HEADER,account.getHeader());
|
||||||
|
values.put(Sqlite.COL_HEADER_STATIC,account.getHeader_static());
|
||||||
|
values.put(Sqlite.COL_CREATED_AT, Helper.dateToString(context, account.getCreated_at()));
|
||||||
|
values.put(Sqlite.COL_INSTANCE, account.getInstance());
|
||||||
|
if( account.getToken() != null)
|
||||||
|
values.put(Sqlite.COL_OAUTHTOKEN, account.getToken());
|
||||||
|
|
||||||
|
return db.update(Sqlite.TABLE_USER_ACCOUNT,
|
||||||
|
values, Sqlite.COL_USER_ID + " = ? AND " + Sqlite.COL_USERNAME + " =?",
|
||||||
|
new String[]{account.getId(), account.getUsername()});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int removeUser(Account account){
|
||||||
|
return db.delete(Sqlite.TABLE_USER_ACCOUNT, Sqlite.COL_USER_ID + " = '" +account.getId() +
|
||||||
|
"' AND " + Sqlite.COL_USERNAME + " = '" + account.getUsername()+ "'", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an Account by id
|
||||||
|
* @param accountId String
|
||||||
|
* @return Account
|
||||||
|
*/
|
||||||
|
public Account getAccountByID(String accountId){
|
||||||
|
|
||||||
|
try {
|
||||||
|
Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, Sqlite.COL_USER_ID + " = '" + accountId + "'", null, null, null, null, "1");
|
||||||
|
return cursorToUser(c);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all Account in db
|
||||||
|
* @return Account List<Account>
|
||||||
|
*/
|
||||||
|
public List<Account> getAllAccount(){
|
||||||
|
|
||||||
|
try {
|
||||||
|
Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, null, null, null, null, null, null);
|
||||||
|
return cursorToListUser(c);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an Account by token
|
||||||
|
* @param token String
|
||||||
|
* @return Account
|
||||||
|
*/
|
||||||
|
public Account getAccountByToken(String token){
|
||||||
|
|
||||||
|
try {
|
||||||
|
Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, Sqlite.COL_OAUTHTOKEN + " = \"" + token + "\"", null, null, null, null, "1");
|
||||||
|
return cursorToUser(c);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the current user is already stored in data base
|
||||||
|
* @param account Account
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean userExist(Account account)
|
||||||
|
{
|
||||||
|
Cursor mCount= db.rawQuery("select count(*) from " + Sqlite.TABLE_USER_ACCOUNT
|
||||||
|
+ " where " + Sqlite.COL_USER_ID + " = '" + account.getId() + "' AND " + Sqlite.COL_USERNAME + " = '" + account.getUsername()+ "'", null);
|
||||||
|
mCount.moveToFirst();
|
||||||
|
int count = mCount.getInt(0);
|
||||||
|
mCount.close();
|
||||||
|
return (count > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Method to hydrate an Account from database
|
||||||
|
* @param c Cursor
|
||||||
|
* @return Account
|
||||||
|
*/
|
||||||
|
private Account cursorToUser(Cursor c){
|
||||||
|
//No element found
|
||||||
|
if (c.getCount() == 0)
|
||||||
|
return null;
|
||||||
|
//Take the first element
|
||||||
|
c.moveToFirst();
|
||||||
|
//New user
|
||||||
|
Account account = new Account();
|
||||||
|
|
||||||
|
account.setId(c.getString(c.getColumnIndex(Sqlite.COL_USER_ID)));
|
||||||
|
account.setUsername(c.getString(c.getColumnIndex(Sqlite.COL_USERNAME)));
|
||||||
|
account.setAcct(c.getString(c.getColumnIndex(Sqlite.COL_ACCT)));
|
||||||
|
account.setDisplay_name(c.getString(c.getColumnIndex(Sqlite.COL_DISPLAYED_NAME)));
|
||||||
|
account.setLocked(c.getInt(c.getColumnIndex(Sqlite.COL_LOCKED)) == 1);
|
||||||
|
account.setFollowers_count(c.getInt(c.getColumnIndex(Sqlite.COL_FOLLOWERS_COUNT)));
|
||||||
|
account.setFollowing_count(c.getInt(c.getColumnIndex(Sqlite.COL_FOLLOWING_COUNT)));
|
||||||
|
account.setStatuses_count(c.getInt(c.getColumnIndex(Sqlite.COL_STATUSES_COUNT)));
|
||||||
|
account.setNote(c.getString(c.getColumnIndex(Sqlite.COL_NOTE)));
|
||||||
|
account.setUrl(c.getString(c.getColumnIndex(Sqlite.COL_URL)));
|
||||||
|
account.setAvatar(c.getString(c.getColumnIndex(Sqlite.COL_AVATAR)));
|
||||||
|
account.setAvatar_static(c.getString(c.getColumnIndex(Sqlite.COL_AVATAR_STATIC)));
|
||||||
|
account.setHeader(c.getString(c.getColumnIndex(Sqlite.COL_HEADER)));
|
||||||
|
account.setHeader_static(c.getString(c.getColumnIndex(Sqlite.COL_HEADER_STATIC)));
|
||||||
|
account.setCreated_at(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_CREATED_AT))));
|
||||||
|
account.setInstance(c.getString(c.getColumnIndex(Sqlite.COL_INSTANCE)));
|
||||||
|
account.setToken(c.getString(c.getColumnIndex(Sqlite.COL_OAUTHTOKEN)));
|
||||||
|
|
||||||
|
//Close the cursor
|
||||||
|
c.close();
|
||||||
|
|
||||||
|
//User is returned
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Method to hydrate an Accounts from database
|
||||||
|
* @param c Cursor
|
||||||
|
* @return List<Account>
|
||||||
|
*/
|
||||||
|
private List<Account> cursorToListUser(Cursor c){
|
||||||
|
//No element found
|
||||||
|
if (c.getCount() == 0)
|
||||||
|
return null;
|
||||||
|
List<Account> accounts = new ArrayList<>();
|
||||||
|
while (c.moveToNext() ) {
|
||||||
|
//New user
|
||||||
|
Account account = new Account();
|
||||||
|
|
||||||
|
account.setId(c.getString(c.getColumnIndex(Sqlite.COL_USER_ID)));
|
||||||
|
account.setUsername(c.getString(c.getColumnIndex(Sqlite.COL_USERNAME)));
|
||||||
|
account.setAcct(c.getString(c.getColumnIndex(Sqlite.COL_ACCT)));
|
||||||
|
account.setDisplay_name(c.getString(c.getColumnIndex(Sqlite.COL_DISPLAYED_NAME)));
|
||||||
|
account.setLocked(c.getInt(c.getColumnIndex(Sqlite.COL_LOCKED)) == 1);
|
||||||
|
account.setFollowers_count(c.getInt(c.getColumnIndex(Sqlite.COL_FOLLOWERS_COUNT)));
|
||||||
|
account.setFollowing_count(c.getInt(c.getColumnIndex(Sqlite.COL_FOLLOWING_COUNT)));
|
||||||
|
account.setStatuses_count(c.getInt(c.getColumnIndex(Sqlite.COL_STATUSES_COUNT)));
|
||||||
|
account.setNote(c.getString(c.getColumnIndex(Sqlite.COL_NOTE)));
|
||||||
|
account.setUrl(c.getString(c.getColumnIndex(Sqlite.COL_URL)));
|
||||||
|
account.setAvatar(c.getString(c.getColumnIndex(Sqlite.COL_AVATAR)));
|
||||||
|
account.setAvatar_static(c.getString(c.getColumnIndex(Sqlite.COL_AVATAR_STATIC)));
|
||||||
|
account.setHeader(c.getString(c.getColumnIndex(Sqlite.COL_HEADER)));
|
||||||
|
account.setHeader_static(c.getString(c.getColumnIndex(Sqlite.COL_HEADER_STATIC)));
|
||||||
|
account.setCreated_at(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_CREATED_AT))));
|
||||||
|
account.setInstance(c.getString(c.getColumnIndex(Sqlite.COL_INSTANCE)));
|
||||||
|
account.setToken(c.getString(c.getColumnIndex(Sqlite.COL_OAUTHTOKEN)));
|
||||||
|
accounts.add(account);
|
||||||
|
}
|
||||||
|
//Close the cursor
|
||||||
|
c.close();
|
||||||
|
//Users list is returned
|
||||||
|
return accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
/* Copyright 2017 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Mastodon Etalab 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 Thomas Schneider; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
package fr.gouv.etalab.mastodon.sqlite;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 23/04/2017.
|
||||||
|
* Manage the DataBase
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public class Sqlite extends SQLiteOpenHelper {
|
||||||
|
|
||||||
|
public static final int DB_VERSION = 1;
|
||||||
|
public static final String DB_NAME = "mastodon_etalab_db";
|
||||||
|
public static SQLiteDatabase db;
|
||||||
|
private static Sqlite sInstance;
|
||||||
|
|
||||||
|
/***
|
||||||
|
* List of tables to manage users and data
|
||||||
|
*/
|
||||||
|
//Table of owned accounts
|
||||||
|
static final String TABLE_USER_ACCOUNT = "USER_ACCOUNT";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static final String COL_USER_ID = "USER_ID";
|
||||||
|
public static final String COL_USERNAME = "USERNAME";
|
||||||
|
public static final String COL_ACCT = "ACCT";
|
||||||
|
public static final String COL_DISPLAYED_NAME = "DISPLAYED_NAME";
|
||||||
|
public static final String COL_LOCKED = "LOCKED";
|
||||||
|
public static final String COL_CREATED_AT = "CREATED_AT";
|
||||||
|
public static final String COL_FOLLOWERS_COUNT = "FOLLOWERS_COUNT";
|
||||||
|
public static final String COL_FOLLOWING_COUNT = "FOLLOWING_COUNT";
|
||||||
|
public static final String COL_STATUSES_COUNT = "STATUSES_COUNT";
|
||||||
|
public static final String COL_NOTE = "NOTE";
|
||||||
|
public static final String COL_URL = "URL";
|
||||||
|
public static final String COL_AVATAR = "AVATAR";
|
||||||
|
public static final String COL_AVATAR_STATIC = "AVATAR_STATIC";
|
||||||
|
public static final String COL_HEADER = "HEADER";
|
||||||
|
public static final String COL_HEADER_STATIC = "HEADER_STATIC";
|
||||||
|
public static final String COL_INSTANCE = "INSTANCE";
|
||||||
|
public static final String COL_OAUTHTOKEN = "OAUTH_TOKEN";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static final String CREATE_TABLE_USER_ACCOUNT = "CREATE TABLE " + TABLE_USER_ACCOUNT + " ("
|
||||||
|
+ COL_USER_ID + " TEXT PRIMARY KEY, " + COL_USERNAME + " TEXT NOT NULL, " + COL_ACCT + " TEXT NOT NULL, "
|
||||||
|
+ COL_DISPLAYED_NAME + " TEXT NOT NULL, " + COL_LOCKED + " INTEGER NOT NULL, "
|
||||||
|
+ COL_FOLLOWERS_COUNT + " INTEGER NOT NULL, " + COL_FOLLOWING_COUNT + " INTEGER NOT NULL, " + COL_STATUSES_COUNT + " INTEGER NOT NULL, "
|
||||||
|
+ COL_NOTE + " TEXT NOT NULL, "+ COL_URL + " TEXT NOT NULL, "
|
||||||
|
+ COL_AVATAR + " TEXT NOT NULL, "+ COL_AVATAR_STATIC + " TEXT NOT NULL, "
|
||||||
|
+ COL_HEADER + " TEXT NOT NULL, "+ COL_HEADER_STATIC + " TEXT NOT NULL, "
|
||||||
|
+ COL_INSTANCE + " TEXT NOT NULL, " + COL_OAUTHTOKEN + " TEXT NOT NULL, " + COL_CREATED_AT + " TEXT NOT NULL)";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Sqlite(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
|
||||||
|
super(context, name, factory, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static synchronized Sqlite getInstance(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
|
||||||
|
{
|
||||||
|
if (sInstance == null) {
|
||||||
|
sInstance = new Sqlite(context, name, factory, version);
|
||||||
|
}
|
||||||
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
db.execSQL(CREATE_TABLE_USER_ACCOUNT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
switch (oldVersion) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SQLiteDatabase open(){
|
||||||
|
//opened with write access
|
||||||
|
db = getWritableDatabase();
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close(){
|
||||||
|
//Close the db
|
||||||
|
if( db != null && db.isOpen() ) {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 720 B |
After Width: | Height: | Size: 795 B |
After Width: | Height: | Size: 469 B |
After Width: | Height: | Size: 613 B |
After Width: | Height: | Size: 638 B |
After Width: | Height: | Size: 445 B |
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 486 B |
After Width: | Height: | Size: 317 B |
After Width: | Height: | Size: 306 B |
After Width: | Height: | Size: 536 B |
After Width: | Height: | Size: 680 B |
After Width: | Height: | Size: 563 B |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 806 B |
After Width: | Height: | Size: 425 B |
After Width: | Height: | Size: 436 B |
After Width: | Height: | Size: 201 B |
After Width: | Height: | Size: 265 B |
After Width: | Height: | Size: 937 B |
After Width: | Height: | Size: 1.6 KiB |