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 |