diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java index f22ab846d..c2ba22f4e 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java @@ -120,8 +120,8 @@ import fr.gouv.etalab.mastodon.fragments.DisplayHowToFragment; import fr.gouv.etalab.mastodon.fragments.DisplayListsFragment; import fr.gouv.etalab.mastodon.fragments.DisplayMutedInstanceFragment; import fr.gouv.etalab.mastodon.fragments.DisplayNotificationsFragment; -import fr.gouv.etalab.mastodon.fragments.DisplayScheduledTootsFragment; import fr.gouv.etalab.mastodon.fragments.DisplayStatusFragment; +import fr.gouv.etalab.mastodon.fragments.TabLayoutScheduleFragment; import fr.gouv.etalab.mastodon.fragments.TabLayoutSettingsFragment; import fr.gouv.etalab.mastodon.fragments.WhoToFollowFragment; import fr.gouv.etalab.mastodon.helper.CrossActions; @@ -2118,10 +2118,10 @@ public abstract class BaseMainActivity extends BaseActivity .replace(R.id.main_app_container, accountsFragment, fragmentTag).commit(); }else if (id == R.id.nav_scheduled) { toot.show(); - DisplayScheduledTootsFragment displayScheduledTootsFragment = new DisplayScheduledTootsFragment(); + TabLayoutScheduleFragment tabLayoutScheduleFragment = new TabLayoutScheduleFragment(); fragmentTag = "SCHEDULED"; fragmentManager.beginTransaction() - .replace(R.id.main_app_container, displayScheduledTootsFragment, fragmentTag).commit(); + .replace(R.id.main_app_container, tabLayoutScheduleFragment, fragmentTag).commit(); }else if (id == R.id.nav_drafts) { DisplayDraftsFragment displayDraftsFragment = new DisplayDraftsFragment(); fragmentTag = "DRAFTS"; diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveScheduledTootsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveScheduledTootsAsyncTask.java index f1757ec75..43c3cb2e3 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveScheduledTootsAsyncTask.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveScheduledTootsAsyncTask.java @@ -18,15 +18,21 @@ import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.os.AsyncTask; import android.os.SystemClock; + import com.evernote.android.job.JobManager; import com.evernote.android.job.JobRequest; + import java.lang.ref.WeakReference; import java.util.List; import java.util.Set; + import fr.gouv.etalab.mastodon.client.Entities.StoredStatus; +import fr.gouv.etalab.mastodon.fragments.DisplayScheduledTootsFragment; import fr.gouv.etalab.mastodon.helper.Helper; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveScheduledTootsInterface; +import fr.gouv.etalab.mastodon.jobs.ScheduledBoostsSyncJob; import fr.gouv.etalab.mastodon.jobs.ScheduledTootsSyncJob; +import fr.gouv.etalab.mastodon.sqlite.BoostScheduleDAO; import fr.gouv.etalab.mastodon.sqlite.Sqlite; import fr.gouv.etalab.mastodon.sqlite.StatusStoredDAO; @@ -42,20 +48,28 @@ public class RetrieveScheduledTootsAsyncTask extends AsyncTask private OnRetrieveScheduledTootsInterface listener; private List storedStatuses; private WeakReference contextReference; + private DisplayScheduledTootsFragment.typeOfSchedule type; - public RetrieveScheduledTootsAsyncTask(Context context, OnRetrieveScheduledTootsInterface onRetrieveScheduledTootsInterface){ + public RetrieveScheduledTootsAsyncTask(Context context, DisplayScheduledTootsFragment.typeOfSchedule type, OnRetrieveScheduledTootsInterface onRetrieveScheduledTootsInterface){ this.contextReference = new WeakReference<>(context); this.listener = onRetrieveScheduledTootsInterface; - + this.type = type; } @Override protected Void doInBackground(Void... params) { SQLiteDatabase db = Sqlite.getInstance(this.contextReference.get(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); //Retrieves job asked by the user - storedStatuses = new StatusStoredDAO(this.contextReference.get(), db).getAllScheduled(); + if( type == DisplayScheduledTootsFragment.typeOfSchedule.TOOT) + storedStatuses = new StatusStoredDAO(this.contextReference.get(), db).getAllScheduled(); + else if(type == DisplayScheduledTootsFragment.typeOfSchedule.BOOST ) + storedStatuses = new BoostScheduleDAO(this.contextReference.get(), db).getAllScheduled(); //Retrieves real jobs still waiting - Set jobRequests = JobManager.instance().getAllJobRequestsForTag(ScheduledTootsSyncJob.SCHEDULED_TOOT); + Set jobRequests = null; + if( type == DisplayScheduledTootsFragment.typeOfSchedule.TOOT) + jobRequests = JobManager.instance().getAllJobRequestsForTag(ScheduledTootsSyncJob.SCHEDULED_TOOT); + else if(type == DisplayScheduledTootsFragment.typeOfSchedule.BOOST ) + jobRequests = JobManager.instance().getAllJobRequestsForTag(ScheduledBoostsSyncJob.SCHEDULED_BOOST); int[] jobIds; if( jobRequests != null && jobRequests.size() > 0 ){ int i = 0; @@ -72,7 +86,10 @@ public class RetrieveScheduledTootsAsyncTask extends AsyncTask for(StoredStatus ss: storedStatuses){ if (!Helper.isJobPresent(jobIds, ss.getJobId())){ //JobId is fixed to -1 which means an error occured (it was never sent) - new StatusStoredDAO(this.contextReference.get(), db).updateJobId(ss.getId(),-1); + if( type == DisplayScheduledTootsFragment.typeOfSchedule.TOOT) + new StatusStoredDAO(this.contextReference.get(), db).updateJobId(ss.getId(),-1); + else if(type == DisplayScheduledTootsFragment.typeOfSchedule.BOOST ) + new BoostScheduleDAO(this.contextReference.get(), db).updateJobId(ss.getId(),-1); } } //Lets time to update db before dispaying diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayScheduledTootsFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayScheduledTootsFragment.java index 47adeeda2..2b851f2fa 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayScheduledTootsFragment.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayScheduledTootsFragment.java @@ -35,15 +35,19 @@ import android.view.ViewGroup; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; + import java.util.List; + +import fr.gouv.etalab.mastodon.R; import fr.gouv.etalab.mastodon.asynctasks.RetrieveScheduledTootsAsyncTask; import fr.gouv.etalab.mastodon.client.Entities.StoredStatus; import fr.gouv.etalab.mastodon.drawers.ScheduledTootsListAdapter; import fr.gouv.etalab.mastodon.helper.Helper; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveScheduledTootsInterface; +import fr.gouv.etalab.mastodon.sqlite.BoostScheduleDAO; import fr.gouv.etalab.mastodon.sqlite.Sqlite; import fr.gouv.etalab.mastodon.sqlite.StatusStoredDAO; -import fr.gouv.etalab.mastodon.R; + import static fr.gouv.etalab.mastodon.helper.Helper.changeDrawableColor; @@ -59,13 +63,22 @@ public class DisplayScheduledTootsFragment extends Fragment implements OnRetriev private RelativeLayout mainLoader, textviewNoAction; private ListView lv_scheduled_toots; private TextView warning_battery_message; + private typeOfSchedule type; + + public enum typeOfSchedule{ + TOOT, + BOOST + } @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_scheduled_toots, container, false); context = getContext(); - + Bundle bundle = new Bundle(); + type = (typeOfSchedule) bundle.get("type"); + if( type == null) + type = typeOfSchedule.TOOT; lv_scheduled_toots = rootView.findViewById(R.id.lv_scheduled_toots); mainLoader = rootView.findViewById(R.id.loader); @@ -75,7 +88,10 @@ public class DisplayScheduledTootsFragment extends Fragment implements OnRetriev //Removes all scheduled toots that have sent SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); - new StatusStoredDAO(context, db).removeAllSent(); + if( type == typeOfSchedule.TOOT) + new StatusStoredDAO(context, db).removeAllSent(); + else if( type == typeOfSchedule.BOOST) + new BoostScheduleDAO(context, db).removeAllSent(); return rootView; } @@ -84,7 +100,7 @@ public class DisplayScheduledTootsFragment extends Fragment implements OnRetriev public void onResume(){ super.onResume(); //Retrieves scheduled toots - asyncTask = new RetrieveScheduledTootsAsyncTask(context, DisplayScheduledTootsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + asyncTask = new RetrieveScheduledTootsAsyncTask(context, type,DisplayScheduledTootsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { final PowerManager powerManager = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE); final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/TabLayoutScheduleFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/TabLayoutScheduleFragment.java new file mode 100644 index 000000000..f3118826f --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/TabLayoutScheduleFragment.java @@ -0,0 +1,112 @@ +package fr.gouv.etalab.mastodon.fragments; +/* Copyright 2018 Thomas Schneider + * + * This file is a part of Mastalab + * + * 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. + * + * Mastalab 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 Mastalab; if not, + * see . */ + +import android.os.Bundle; +import android.support.annotation.NonNull; +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 fr.gouv.etalab.mastodon.R; + + +/** + * Created by Thomas on 09/12/2018. + * Tablayout for schedules + */ + +public class TabLayoutScheduleFragment extends Fragment { + + + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View inflatedView = inflater.inflate(R.layout.tablayout_toots, container, false); + + TabLayout tabLayout = inflatedView.findViewById(R.id.tabLayout); + tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.toots))); + tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.reblog))); + final 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: + DisplayScheduledTootsFragment displayScheduledTootsFragment = new DisplayScheduledTootsFragment(); + Bundle bundle = new Bundle(); + bundle.putSerializable("type", DisplayScheduledTootsFragment.typeOfSchedule.TOOT); + displayScheduledTootsFragment.setArguments(bundle); + return displayScheduledTootsFragment; + case 1: + displayScheduledTootsFragment = new DisplayScheduledTootsFragment(); + bundle = new Bundle(); + bundle.putSerializable("type", DisplayScheduledTootsFragment.typeOfSchedule.BOOST); + displayScheduledTootsFragment.setArguments(bundle); + default: + displayScheduledTootsFragment = new DisplayScheduledTootsFragment(); + bundle = new Bundle(); + bundle.putSerializable("type", DisplayScheduledTootsFragment.typeOfSchedule.TOOT); + displayScheduledTootsFragment.setArguments(bundle); + return displayScheduledTootsFragment; + } + } + + @Override + public int getCount() { + return mNumOfTabs; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/ScheduledBoostsSyncJob.java b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/ScheduledBoostsSyncJob.java new file mode 100644 index 000000000..83c193a6d --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/ScheduledBoostsSyncJob.java @@ -0,0 +1,97 @@ +package fr.gouv.etalab.mastodon.jobs; +/* Copyright 2018 Thomas Schneider + * + * This file is a part of Mastalab + * + * 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. + * + * Mastalab 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 Mastalab; if not, + * see . */ + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.support.annotation.NonNull; + +import com.evernote.android.job.Job; +import com.evernote.android.job.JobRequest; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +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.client.Entities.StoredStatus; +import fr.gouv.etalab.mastodon.helper.Helper; +import fr.gouv.etalab.mastodon.sqlite.AccountDAO; +import fr.gouv.etalab.mastodon.sqlite.BoostScheduleDAO; +import fr.gouv.etalab.mastodon.sqlite.Sqlite; + + +/** + * Created by Thomas on 09/12/2018. + * Scheduled a boost a datetime + */ + +public class ScheduledBoostsSyncJob extends Job { + + public static final String SCHEDULED_BOOST = "job_scheduled_boost"; + static { + Helper.installProvider(); + } + + @NonNull + @Override + protected Result onRunJob(@NonNull Params params) { + //Code refresh here + int jobId = params.getId(); + SQLiteDatabase db = Sqlite.getInstance(getContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + //Retrieves the stored status + StoredStatus storedStatus = new BoostScheduleDAO(getContext(), db).getStatusScheduled(jobId); + if( storedStatus != null){ + String userId = storedStatus.getUserId(); + String instance = storedStatus.getInstance(); + if( instance != null && userId != null){ + Account account = new AccountDAO(getContext(), db).getAccountByUserIDInstance(userId, instance); + if( account != null){ + //Retrieves the linked status to toot + Status status = storedStatus.getStatus(); + if( status != null){ + int statusCode = new API(getContext(), account.getInstance(), account.getToken()).statusAction(status); + //Toot was sent + if( statusCode == 200){ + new BoostScheduleDAO(getContext(), db).updateScheduledDone(jobId, new Date()); + } + } + } + } + } + return Result.SUCCESS; + } + + + public static int schedule(Context context, Status status, long id, long timestampScheduling){ + + long startMs = (timestampScheduling - new Date().getTime()); + long endMs = startMs + TimeUnit.MINUTES.toMillis(5); + SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + + int jobId = new JobRequest.Builder(ScheduledBoostsSyncJob.SCHEDULED_BOOST) + .setExecutionWindow(startMs, endMs) + .setUpdateCurrent(false) + .setRequiredNetworkType(JobRequest.NetworkType.METERED) + .setRequirementsEnforced(false) + .build() + .schedule(); + new BoostScheduleDAO(context, db).insert(status, id, jobId, new Date(timestampScheduling)); + return jobId; + } + + +}