mirror of
				https://codeberg.org/tom79/Fedilab.git
				synced 2025-10-20 11:20:16 +03:00 
			
		
		
		
	Prepare db for caching bundle + logic to pass/get data
This commit is contained in:
		
							parent
							
								
									36e258adb3
								
							
						
					
					
						commit
						8040a06300
					
				
					 4 changed files with 343 additions and 93 deletions
				
			
		|  | @ -0,0 +1,228 @@ | ||||||
|  | package app.fedilab.android.mastodon.client.entities.app; | ||||||
|  | /* Copyright 2024 Thomas Schneider | ||||||
|  |  * | ||||||
|  |  * This file is a part of Fedilab | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify it under the terms of the | ||||||
|  |  * GNU General Public License as published by the Free Software Foundation; either version 3 of the | ||||||
|  |  * License, or (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even | ||||||
|  |  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General | ||||||
|  |  * Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License along with Fedilab; if not, | ||||||
|  |  * see <http://www.gnu.org/licenses>. */ | ||||||
|  | 
 | ||||||
|  | import android.content.ContentValues; | ||||||
|  | import android.content.Context; | ||||||
|  | import android.database.Cursor; | ||||||
|  | import android.database.sqlite.SQLiteDatabase; | ||||||
|  | import android.os.Bundle; | ||||||
|  | import android.os.Handler; | ||||||
|  | import android.os.Looper; | ||||||
|  | import android.os.Parcel; | ||||||
|  | import android.util.Base64; | ||||||
|  | 
 | ||||||
|  | import java.io.BufferedOutputStream; | ||||||
|  | import java.io.ByteArrayInputStream; | ||||||
|  | import java.io.ByteArrayOutputStream; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.zip.GZIPInputStream; | ||||||
|  | import java.util.zip.GZIPOutputStream; | ||||||
|  | 
 | ||||||
|  | import app.fedilab.android.mastodon.exception.DBException; | ||||||
|  | import app.fedilab.android.mastodon.helper.Helper; | ||||||
|  | import app.fedilab.android.sqlite.Sqlite; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Class that manages Bundle of Intent from database | ||||||
|  |  */ | ||||||
|  | public class CachedBundle { | ||||||
|  | 
 | ||||||
|  |     public String id; | ||||||
|  |     public Bundle bundle; | ||||||
|  |     public Date created_at; | ||||||
|  | 
 | ||||||
|  |     private SQLiteDatabase db; | ||||||
|  | 
 | ||||||
|  |     private transient Context context; | ||||||
|  | 
 | ||||||
|  |     public CachedBundle() {} | ||||||
|  |     public CachedBundle(Context context) { | ||||||
|  |         //Creation of the DB with tables | ||||||
|  |         this.context = context; | ||||||
|  |         this.db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Insert a bundle in db | ||||||
|  |      * | ||||||
|  |      * @param bundle {@link Bundle} | ||||||
|  |      * @return long - db id | ||||||
|  |      * @throws DBException exception with database | ||||||
|  |      */ | ||||||
|  |     private long insertIntent(Bundle bundle) throws DBException { | ||||||
|  |         if (db == null) { | ||||||
|  |             throw new DBException("db is null. Wrong initialization."); | ||||||
|  |         } | ||||||
|  |         ContentValues values = new ContentValues(); | ||||||
|  |         values.put(Sqlite.COL_BUNDLE, serializeBundle(bundle)); | ||||||
|  |         values.put(Sqlite.COL_CREATED_AT, Helper.dateToString(new Date())); | ||||||
|  |         //Inserts token | ||||||
|  |         try { | ||||||
|  |             return db.insertOrThrow(Sqlite.TABLE_INTENT, null, values); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |             return -1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public interface BundleCallback{ | ||||||
|  |         public void get(Bundle bundle); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public interface BundleInsertCallback{ | ||||||
|  |         public void inserted(long bundleId); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void getBundle(long id, BundleCallback callback) { | ||||||
|  |         new Thread(()->{ | ||||||
|  |             Bundle bundle = null; | ||||||
|  |             try { | ||||||
|  |                 CachedBundle cachedBundle = getCachedBundle(String.valueOf(id)); | ||||||
|  |                 if (cachedBundle != null) { | ||||||
|  |                     bundle = cachedBundle.bundle; | ||||||
|  |                 } | ||||||
|  |                 removeIntent(String.valueOf(id)); | ||||||
|  |             } catch (DBException ignored) {} | ||||||
|  |             Handler mainHandler = new Handler(Looper.getMainLooper()); | ||||||
|  |             Bundle finalBundle = bundle; | ||||||
|  |             Runnable myRunnable = () -> callback.get(finalBundle); | ||||||
|  |             mainHandler.post(myRunnable); | ||||||
|  |         }).start(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void insertBundle(Bundle bundle, BundleInsertCallback callback) { | ||||||
|  |         new Thread(()->{ | ||||||
|  |             long dbBundleId = -1; | ||||||
|  |             try { | ||||||
|  |                 dbBundleId = insertIntent(bundle); | ||||||
|  |             } catch (DBException ignored) {} | ||||||
|  |             Handler mainHandler = new Handler(Looper.getMainLooper()); | ||||||
|  |             long finalDbBundleId = dbBundleId; | ||||||
|  |             Runnable myRunnable = () -> callback.inserted(finalDbBundleId); | ||||||
|  |             mainHandler.post(myRunnable); | ||||||
|  |         }).start(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a bundle by its ID | ||||||
|  |      * | ||||||
|  |      * @param id String | ||||||
|  |      * @return CachedBundle {@link CachedBundle} | ||||||
|  |      */ | ||||||
|  |     private CachedBundle getCachedBundle(String id) throws DBException { | ||||||
|  |         if (db == null) { | ||||||
|  |             throw new DBException("db is null. Wrong initialization."); | ||||||
|  |         } | ||||||
|  |         try { | ||||||
|  |             Cursor c = db.query(Sqlite.TABLE_INTENT, null, Sqlite.COL_ID + " = \"" + id + "\"", null, null, null, null, "1"); | ||||||
|  |             return cursorToCachedBundle(c); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Remove a bundle from db | ||||||
|  |      * | ||||||
|  |      * @param id - intent id | ||||||
|  |      */ | ||||||
|  |     private void removeIntent(String id) throws DBException { | ||||||
|  |         if (db == null) { | ||||||
|  |             throw new DBException("db is null. Wrong initialization."); | ||||||
|  |         } | ||||||
|  |         db.delete(Sqlite.TABLE_INTENT, Sqlite.COL_ID + " = '" + id + "'", null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     /*** | ||||||
|  |      * Method to hydrate an CachedBundle from database | ||||||
|  |      * @param c Cursor | ||||||
|  |      * @return CachedBundle {@link CachedBundle} | ||||||
|  |      */ | ||||||
|  |     private CachedBundle cursorToCachedBundle(Cursor c) { | ||||||
|  |         //No element found | ||||||
|  |         if (c.getCount() == 0) { | ||||||
|  |             c.close(); | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         //Take the first element | ||||||
|  |         c.moveToFirst(); | ||||||
|  |         //New user | ||||||
|  |         CachedBundle account = convertCursorToCachedBundle(c); | ||||||
|  |         //Close the cursor | ||||||
|  |         c.close(); | ||||||
|  |         return account; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Read cursor and hydrate without closing it | ||||||
|  |      * | ||||||
|  |      * @param c - Cursor | ||||||
|  |      * @return BaseAccount | ||||||
|  |      */ | ||||||
|  |     private CachedBundle convertCursorToCachedBundle(Cursor c) { | ||||||
|  |         CachedBundle cachedBundle = new CachedBundle(); | ||||||
|  |         cachedBundle.id = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_ID)); | ||||||
|  |         cachedBundle.bundle = deserializeBundle(c.getString(c.getColumnIndexOrThrow(Sqlite.COL_BUNDLE))); | ||||||
|  |         cachedBundle.created_at = Helper.stringToDate(context, c.getString(c.getColumnIndexOrThrow(Sqlite.COL_CREATED_AT))); | ||||||
|  |         return cachedBundle; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private String serializeBundle(final Bundle bundle) { | ||||||
|  |         String base64 = null; | ||||||
|  |         final Parcel parcel = Parcel.obtain(); | ||||||
|  |         try { | ||||||
|  |             parcel.writeBundle(bundle); | ||||||
|  |             final ByteArrayOutputStream bos = new ByteArrayOutputStream(); | ||||||
|  |             final GZIPOutputStream zos = new GZIPOutputStream(new BufferedOutputStream(bos)); | ||||||
|  |             zos.write(parcel.marshall()); | ||||||
|  |             zos.close(); | ||||||
|  |             base64 = Base64.encodeToString(bos.toByteArray(), 0); | ||||||
|  |         } catch(IOException e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |         } finally { | ||||||
|  |             parcel.recycle(); | ||||||
|  |         } | ||||||
|  |         return base64; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private Bundle deserializeBundle(final String base64) { | ||||||
|  |         Bundle bundle = null; | ||||||
|  |         final Parcel parcel = Parcel.obtain(); | ||||||
|  |         try { | ||||||
|  |             final ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); | ||||||
|  |             final byte[] buffer = new byte[1024]; | ||||||
|  |             final GZIPInputStream zis = new GZIPInputStream(new ByteArrayInputStream(Base64.decode(base64, 0))); | ||||||
|  |             int len; | ||||||
|  |             while ((len = zis.read(buffer)) != -1) { | ||||||
|  |                 byteBuffer.write(buffer, 0, len); | ||||||
|  |             } | ||||||
|  |             zis.close(); | ||||||
|  |             parcel.unmarshall(byteBuffer.toByteArray(), 0, byteBuffer.size()); | ||||||
|  |             parcel.setDataPosition(0); | ||||||
|  |             bundle = parcel.readBundle(getClass().getClassLoader()); | ||||||
|  |         } catch (IOException e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |         }  finally { | ||||||
|  |             parcel.recycle(); | ||||||
|  |         } | ||||||
|  |         return bundle; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -210,6 +210,8 @@ public class Helper { | ||||||
|     public static final String RECEIVE_REDRAW_PROFILE = "RECEIVE_REDRAW_PROFILE"; |     public static final String RECEIVE_REDRAW_PROFILE = "RECEIVE_REDRAW_PROFILE"; | ||||||
| 
 | 
 | ||||||
|     public static final String ARG_TIMELINE_TYPE = "ARG_TIMELINE_TYPE"; |     public static final String ARG_TIMELINE_TYPE = "ARG_TIMELINE_TYPE"; | ||||||
|  | 
 | ||||||
|  |     public static final String ARG_INTENT_ID = "ARG_INTENT_ID"; | ||||||
|     public static final String ARG_PEERTUBE_NAV_REMOTE = "ARG_PEERTUBE_NAV_REMOTE"; |     public static final String ARG_PEERTUBE_NAV_REMOTE = "ARG_PEERTUBE_NAV_REMOTE"; | ||||||
| 
 | 
 | ||||||
|     public static final String ARG_REMOTE_INSTANCE_STRING = "ARG_REMOTE_INSTANCE_STRING"; |     public static final String ARG_REMOTE_INSTANCE_STRING = "ARG_REMOTE_INSTANCE_STRING"; | ||||||
|  |  | ||||||
|  | @ -57,10 +57,12 @@ import app.fedilab.android.mastodon.client.entities.api.Pagination; | ||||||
| import app.fedilab.android.mastodon.client.entities.api.Status; | import app.fedilab.android.mastodon.client.entities.api.Status; | ||||||
| import app.fedilab.android.mastodon.client.entities.api.Statuses; | import app.fedilab.android.mastodon.client.entities.api.Statuses; | ||||||
| import app.fedilab.android.mastodon.client.entities.app.BubbleTimeline; | import app.fedilab.android.mastodon.client.entities.app.BubbleTimeline; | ||||||
|  | import app.fedilab.android.mastodon.client.entities.app.CachedBundle; | ||||||
| import app.fedilab.android.mastodon.client.entities.app.PinnedTimeline; | import app.fedilab.android.mastodon.client.entities.app.PinnedTimeline; | ||||||
| import app.fedilab.android.mastodon.client.entities.app.RemoteInstance; | import app.fedilab.android.mastodon.client.entities.app.RemoteInstance; | ||||||
| import app.fedilab.android.mastodon.client.entities.app.TagTimeline; | import app.fedilab.android.mastodon.client.entities.app.TagTimeline; | ||||||
| import app.fedilab.android.mastodon.client.entities.app.Timeline; | import app.fedilab.android.mastodon.client.entities.app.Timeline; | ||||||
|  | import app.fedilab.android.mastodon.exception.DBException; | ||||||
| import app.fedilab.android.mastodon.helper.CrossActionHelper; | import app.fedilab.android.mastodon.helper.CrossActionHelper; | ||||||
| import app.fedilab.android.mastodon.helper.GlideApp; | import app.fedilab.android.mastodon.helper.GlideApp; | ||||||
| import app.fedilab.android.mastodon.helper.Helper; | import app.fedilab.android.mastodon.helper.Helper; | ||||||
|  | @ -346,29 +348,12 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. | ||||||
|     @Override |     @Override | ||||||
|     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { |     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { | ||||||
|         super.onViewCreated(view, savedInstanceState); |         super.onViewCreated(view, savedInstanceState); | ||||||
|         timelinesVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, TimelinesVM.class); |  | ||||||
|         accountsVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, AccountsVM.class); |  | ||||||
|         initialStatuses = null; |  | ||||||
|         lockForResumeCall = 0; |  | ||||||
|         binding.loader.setVisibility(View.VISIBLE); |         binding.loader.setVisibility(View.VISIBLE); | ||||||
|         binding.recyclerView.setVisibility(View.GONE); |         binding.recyclerView.setVisibility(View.GONE); | ||||||
|         SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()); |  | ||||||
|         max_id = statusReport != null ? statusReport.id : null; |  | ||||||
|         offset = 0; |  | ||||||
| 
 |  | ||||||
|         rememberPosition = sharedpreferences.getBoolean(getString(R.string.SET_REMEMBER_POSITION), true); |  | ||||||
|         //Inner marker are only for pinned timelines and main timelines, they have isViewInitialized set to false |  | ||||||
|         if (max_id == null && !isViewInitialized && rememberPosition) { |  | ||||||
|             max_id = sharedpreferences.getString(getString(R.string.SET_INNER_MARKER) + BaseMainActivity.currentUserID + BaseMainActivity.currentInstance + slug, null); |  | ||||||
|         } |  | ||||||
|         if (search != null) { |         if (search != null) { | ||||||
|             binding.swipeContainer.setRefreshing(false); |             binding.swipeContainer.setRefreshing(false); | ||||||
|             binding.swipeContainer.setEnabled(false); |             binding.swipeContainer.setEnabled(false); | ||||||
|         } |         } | ||||||
|         //Only fragment in main view pager should not have the view initialized |  | ||||||
|         //AND Only the first fragment will initialize its view |  | ||||||
|         flagLoading = false; |  | ||||||
| 
 |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | @ -378,91 +363,114 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. | ||||||
| 
 | 
 | ||||||
|     public View onCreateView(@NonNull LayoutInflater inflater, |     public View onCreateView(@NonNull LayoutInflater inflater, | ||||||
|                              ViewGroup container, Bundle savedInstanceState) { |                              ViewGroup container, Bundle savedInstanceState) { | ||||||
|  |         timelinesVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, TimelinesVM.class); | ||||||
|  |         accountsVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, AccountsVM.class); | ||||||
|  |         initialStatuses = null; | ||||||
|  |         lockForResumeCall = 0; | ||||||
|         timelineType = Timeline.TimeLineEnum.HOME; |         timelineType = Timeline.TimeLineEnum.HOME; | ||||||
|         canBeFederated = true; |         canBeFederated = true; | ||||||
|         retry_for_home_done = false; |         retry_for_home_done = false; | ||||||
|         if (getArguments() != null) { |  | ||||||
|             timelineType = (Timeline.TimeLineEnum) getArguments().get(Helper.ARG_TIMELINE_TYPE); |  | ||||||
|             lemmy_post_id = getArguments().getString(Helper.ARG_LEMMY_POST_ID, null); |  | ||||||
|             list_id = getArguments().getString(Helper.ARG_LIST_ID, null); |  | ||||||
|             search = getArguments().getString(Helper.ARG_SEARCH_KEYWORD, null); |  | ||||||
|             searchCache = getArguments().getString(Helper.ARG_SEARCH_KEYWORD_CACHE, null); |  | ||||||
|             pinnedTimeline = (PinnedTimeline) getArguments().getSerializable(Helper.ARG_REMOTE_INSTANCE); |  | ||||||
|             if (pinnedTimeline != null && pinnedTimeline.remoteInstance != null) { |  | ||||||
|                 if (pinnedTimeline.remoteInstance.type != RemoteInstance.InstanceType.NITTER) { |  | ||||||
|                     remoteInstance = pinnedTimeline.remoteInstance.host; |  | ||||||
|                 } else { |  | ||||||
|                     SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()); |  | ||||||
|                     remoteInstance = sharedpreferences.getString(getString(R.string.SET_NITTER_HOST), getString(R.string.DEFAULT_NITTER_HOST)).toLowerCase(); |  | ||||||
|                     canBeFederated = false; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             if (timelineType == Timeline.TimeLineEnum.TREND_MESSAGE_PUBLIC) { |  | ||||||
|                 canBeFederated = false; |  | ||||||
|             } |  | ||||||
|             publicTrendsDomain = getArguments().getString(Helper.ARG_REMOTE_INSTANCE_STRING, null); |  | ||||||
|             isViewInitialized = getArguments().getBoolean(Helper.ARG_INITIALIZE_VIEW, true); |  | ||||||
|             isNotPinnedTimeline = isViewInitialized; |  | ||||||
|             tagTimeline = (TagTimeline) getArguments().getSerializable(Helper.ARG_TAG_TIMELINE); |  | ||||||
|             bubbleTimeline = (BubbleTimeline) getArguments().getSerializable(Helper.ARG_BUBBLE_TIMELINE); |  | ||||||
|             accountTimeline = (Account) getArguments().getSerializable(Helper.ARG_ACCOUNT); |  | ||||||
|             exclude_replies = !getArguments().getBoolean(Helper.ARG_SHOW_REPLIES, true); |  | ||||||
|             checkRemotely = getArguments().getBoolean(Helper.ARG_CHECK_REMOTELY, false); |  | ||||||
|             show_pinned = getArguments().getBoolean(Helper.ARG_SHOW_PINNED, false); |  | ||||||
|             exclude_reblogs = !getArguments().getBoolean(Helper.ARG_SHOW_REBLOGS, true); |  | ||||||
|             media_only = getArguments().getBoolean(Helper.ARG_SHOW_MEDIA_ONY, false); |  | ||||||
|             viewModelKey = getArguments().getString(Helper.ARG_VIEW_MODEL_KEY, ""); |  | ||||||
|             minified = getArguments().getBoolean(Helper.ARG_MINIFIED, false); |  | ||||||
|             statusReport = (Status) getArguments().getSerializable(Helper.ARG_STATUS_REPORT); |  | ||||||
|             initialStatus = (Status) getArguments().getSerializable(Helper.ARG_STATUS); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         //When visiting a profile without being authenticated |  | ||||||
|         if (checkRemotely) { |  | ||||||
|             String[] acctArray = accountTimeline.acct.split("@"); |  | ||||||
|             if (acctArray.length > 1) { |  | ||||||
|                 remoteInstance = acctArray[1]; |  | ||||||
|             } |  | ||||||
|             if (remoteInstance != null && remoteInstance.equalsIgnoreCase(currentInstance)) { |  | ||||||
|                 checkRemotely = false; |  | ||||||
|             } else if (remoteInstance == null) { |  | ||||||
|                 checkRemotely = false; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         if (tagTimeline != null) { |  | ||||||
|             ident = "@T@" + tagTimeline.name; |  | ||||||
|             if (tagTimeline.isART) { |  | ||||||
|                 timelineType = Timeline.TimeLineEnum.ART; |  | ||||||
|             } |  | ||||||
|         } else if (bubbleTimeline != null) { |  | ||||||
|             ident = "@B@Bubble"; |  | ||||||
|         } else if (list_id != null) { |  | ||||||
|             ident = "@l@" + list_id; |  | ||||||
|         } else if (remoteInstance != null && !checkRemotely) { |  | ||||||
|             if (pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.NITTER) { |  | ||||||
|                 ident = "@R@" + pinnedTimeline.remoteInstance.host; |  | ||||||
|             } else { |  | ||||||
|                 ident = "@R@" + remoteInstance; |  | ||||||
|             } |  | ||||||
|         } else if (search != null) { |  | ||||||
|             ident = "@S@" + search; |  | ||||||
|         } else { |  | ||||||
|             ident = null; |  | ||||||
|         } |  | ||||||
|         if (timelineType != null) { |  | ||||||
|             slug = timelineType != Timeline.TimeLineEnum.ART ? timelineType.getValue() + (ident != null ? "|" + ident : "") : Timeline.TimeLineEnum.TAG.getValue() + (ident != null ? "|" + ident : ""); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         ContextCompat.registerReceiver(requireActivity(), receive_action, new IntentFilter(Helper.RECEIVE_STATUS_ACTION), ContextCompat.RECEIVER_NOT_EXPORTED); |  | ||||||
|         binding = FragmentPaginationBinding.inflate(inflater, container, false); |         binding = FragmentPaginationBinding.inflate(inflater, container, false); | ||||||
|         SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()); |         SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()); | ||||||
|  |         max_id = statusReport != null ? statusReport.id : null; | ||||||
|  |         offset = 0; | ||||||
|  |         rememberPosition = sharedpreferences.getBoolean(getString(R.string.SET_REMEMBER_POSITION), true); | ||||||
|  |         //Inner marker are only for pinned timelines and main timelines, they have isViewInitialized set to false | ||||||
|  |         if (max_id == null && !isViewInitialized && rememberPosition) { | ||||||
|  |             max_id = sharedpreferences.getString(getString(R.string.SET_INNER_MARKER) + BaseMainActivity.currentUserID + BaseMainActivity.currentInstance + slug, null); | ||||||
|  |         } | ||||||
|  |         //Only fragment in main view pager should not have the view initialized | ||||||
|  |         //AND Only the first fragment will initialize its view | ||||||
|  |         flagLoading = false; | ||||||
|  |         if (getArguments() != null) { | ||||||
|  |             long bundleId = getArguments().getLong(Helper.ARG_INTENT_ID, -1); | ||||||
|  |             new CachedBundle(requireActivity()).getBundle(bundleId, this::initializeAfterBundle); | ||||||
|  |         } | ||||||
|         boolean displayScrollBar = sharedpreferences.getBoolean(getString(R.string.SET_TIMELINE_SCROLLBAR), false); |         boolean displayScrollBar = sharedpreferences.getBoolean(getString(R.string.SET_TIMELINE_SCROLLBAR), false); | ||||||
|         binding.recyclerView.setVerticalScrollBarEnabled(displayScrollBar); |         binding.recyclerView.setVerticalScrollBarEnabled(displayScrollBar); | ||||||
|         return binding.getRoot(); |         return binding.getRoot(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private void initializeAfterBundle(Bundle bundle) { | ||||||
|  |         new Thread(()->{ | ||||||
|  |             if (bundle != null) { | ||||||
|  |                 timelineType = (Timeline.TimeLineEnum) bundle.get(Helper.ARG_TIMELINE_TYPE); | ||||||
|  |                 lemmy_post_id = bundle.getString(Helper.ARG_LEMMY_POST_ID, null); | ||||||
|  |                 list_id = bundle.getString(Helper.ARG_LIST_ID, null); | ||||||
|  |                 search = bundle.getString(Helper.ARG_SEARCH_KEYWORD, null); | ||||||
|  |                 searchCache = bundle.getString(Helper.ARG_SEARCH_KEYWORD_CACHE, null); | ||||||
|  |                 pinnedTimeline = (PinnedTimeline) bundle.getSerializable(Helper.ARG_REMOTE_INSTANCE); | ||||||
|  |                 if (pinnedTimeline != null && pinnedTimeline.remoteInstance != null) { | ||||||
|  |                     if (pinnedTimeline.remoteInstance.type != RemoteInstance.InstanceType.NITTER) { | ||||||
|  |                         remoteInstance = pinnedTimeline.remoteInstance.host; | ||||||
|  |                     } else { | ||||||
|  |                         SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()); | ||||||
|  |                         remoteInstance = sharedpreferences.getString(getString(R.string.SET_NITTER_HOST), getString(R.string.DEFAULT_NITTER_HOST)).toLowerCase(); | ||||||
|  |                         canBeFederated = false; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 if (timelineType == Timeline.TimeLineEnum.TREND_MESSAGE_PUBLIC) { | ||||||
|  |                     canBeFederated = false; | ||||||
|  |                 } | ||||||
|  |                 publicTrendsDomain = bundle.getString(Helper.ARG_REMOTE_INSTANCE_STRING, null); | ||||||
|  |                 isViewInitialized = bundle.getBoolean(Helper.ARG_INITIALIZE_VIEW, true); | ||||||
|  |                 isNotPinnedTimeline = isViewInitialized; | ||||||
|  |                 tagTimeline = (TagTimeline) bundle.getSerializable(Helper.ARG_TAG_TIMELINE); | ||||||
|  |                 bubbleTimeline = (BubbleTimeline) bundle.getSerializable(Helper.ARG_BUBBLE_TIMELINE); | ||||||
|  |                 accountTimeline = (Account) bundle.getSerializable(Helper.ARG_ACCOUNT); | ||||||
|  |                 exclude_replies = !bundle.getBoolean(Helper.ARG_SHOW_REPLIES, true); | ||||||
|  |                 checkRemotely = bundle.getBoolean(Helper.ARG_CHECK_REMOTELY, false); | ||||||
|  |                 show_pinned = bundle.getBoolean(Helper.ARG_SHOW_PINNED, false); | ||||||
|  |                 exclude_reblogs = !bundle.getBoolean(Helper.ARG_SHOW_REBLOGS, true); | ||||||
|  |                 media_only = bundle.getBoolean(Helper.ARG_SHOW_MEDIA_ONY, false); | ||||||
|  |                 viewModelKey = bundle.getString(Helper.ARG_VIEW_MODEL_KEY, ""); | ||||||
|  |                 minified = bundle.getBoolean(Helper.ARG_MINIFIED, false); | ||||||
|  |                 statusReport = (Status) bundle.getSerializable(Helper.ARG_STATUS_REPORT); | ||||||
|  |                 initialStatus = (Status) bundle.getSerializable(Helper.ARG_STATUS); | ||||||
|  |             } | ||||||
|  |             Handler mainHandler = new Handler(Looper.getMainLooper()); | ||||||
|  |             Runnable myRunnable = () -> { | ||||||
|  |                 //When visiting a profile without being authenticated | ||||||
|  |                 if (checkRemotely) { | ||||||
|  |                     String[] acctArray = accountTimeline.acct.split("@"); | ||||||
|  |                     if (acctArray.length > 1) { | ||||||
|  |                         remoteInstance = acctArray[1]; | ||||||
|  |                     } | ||||||
|  |                     if (remoteInstance != null && remoteInstance.equalsIgnoreCase(currentInstance)) { | ||||||
|  |                         checkRemotely = false; | ||||||
|  |                     } else if (remoteInstance == null) { | ||||||
|  |                         checkRemotely = false; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 if (tagTimeline != null) { | ||||||
|  |                     ident = "@T@" + tagTimeline.name; | ||||||
|  |                     if (tagTimeline.isART) { | ||||||
|  |                         timelineType = Timeline.TimeLineEnum.ART; | ||||||
|  |                     } | ||||||
|  |                 } else if (bubbleTimeline != null) { | ||||||
|  |                     ident = "@B@Bubble"; | ||||||
|  |                 } else if (list_id != null) { | ||||||
|  |                     ident = "@l@" + list_id; | ||||||
|  |                 } else if (remoteInstance != null && !checkRemotely) { | ||||||
|  |                     if (pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.NITTER) { | ||||||
|  |                         ident = "@R@" + pinnedTimeline.remoteInstance.host; | ||||||
|  |                     } else { | ||||||
|  |                         ident = "@R@" + remoteInstance; | ||||||
|  |                     } | ||||||
|  |                 } else if (search != null) { | ||||||
|  |                     ident = "@S@" + search; | ||||||
|  |                 } else { | ||||||
|  |                     ident = null; | ||||||
|  |                 } | ||||||
|  |                 if (timelineType != null) { | ||||||
|  |                     slug = timelineType != Timeline.TimeLineEnum.ART ? timelineType.getValue() + (ident != null ? "|" + ident : "") : Timeline.TimeLineEnum.TAG.getValue() + (ident != null ? "|" + ident : ""); | ||||||
|  |                 } | ||||||
|  |                 ContextCompat.registerReceiver(requireActivity(), receive_action, new IntentFilter(Helper.RECEIVE_STATUS_ACTION), ContextCompat.RECEIVER_NOT_EXPORTED); | ||||||
|  |             }; | ||||||
|  |             mainHandler.post(myRunnable); | ||||||
|  |         }).start(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Update view and pagination when scrolling down |      * Update view and pagination when scrolling down | ||||||
|      * |      * | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ import android.database.sqlite.SQLiteOpenHelper; | ||||||
| public class Sqlite extends SQLiteOpenHelper { | public class Sqlite extends SQLiteOpenHelper { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     public static final int DB_VERSION = 11; |     public static final int DB_VERSION = 12; | ||||||
|     public static final String DB_NAME = "fedilab_db"; |     public static final String DB_NAME = "fedilab_db"; | ||||||
| 
 | 
 | ||||||
|     //Table of owned accounts |     //Table of owned accounts | ||||||
|  | @ -105,6 +105,9 @@ public class Sqlite extends SQLiteOpenHelper { | ||||||
|     public static final String COL_TAG = "TAG"; |     public static final String COL_TAG = "TAG"; | ||||||
| 
 | 
 | ||||||
|     public static final String TABLE_TIMELINE_CACHE_LOGS = "TIMELINE_CACHE_LOGS"; |     public static final String TABLE_TIMELINE_CACHE_LOGS = "TIMELINE_CACHE_LOGS"; | ||||||
|  |     public static final String TABLE_INTENT = "INTENT"; | ||||||
|  | 
 | ||||||
|  |     public static final String COL_BUNDLE = "BUNDLE"; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     private static final String CREATE_TABLE_USER_ACCOUNT = "CREATE TABLE " + TABLE_USER_ACCOUNT + " (" |     private static final String CREATE_TABLE_USER_ACCOUNT = "CREATE TABLE " + TABLE_USER_ACCOUNT + " (" | ||||||
|  | @ -233,6 +236,12 @@ public class Sqlite extends SQLiteOpenHelper { | ||||||
|             + COL_TYPE + " TEXT NOT NULL, " |             + COL_TYPE + " TEXT NOT NULL, " | ||||||
|             + COL_CREATED_AT + " TEXT NOT NULL)"; |             + COL_CREATED_AT + " TEXT NOT NULL)"; | ||||||
| 
 | 
 | ||||||
|  |     private final String CREATE_TABLE_INTENT = "CREATE TABLE " | ||||||
|  |             + TABLE_INTENT + "(" | ||||||
|  |             + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " | ||||||
|  |             + COL_BUNDLE + " TEXT NOT NULL, " | ||||||
|  |             + COL_CREATED_AT + " TEXT NOT NULL)"; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
|     public Sqlite(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { |     public Sqlite(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { | ||||||
|         super(context, name, factory, version); |         super(context, name, factory, version); | ||||||
|  | @ -263,6 +272,7 @@ public class Sqlite extends SQLiteOpenHelper { | ||||||
|         db.execSQL(CREATE_TABLE_STORED_INSTANCES); |         db.execSQL(CREATE_TABLE_STORED_INSTANCES); | ||||||
|         db.execSQL(CREATE_TABLE_CACHE_TAGS); |         db.execSQL(CREATE_TABLE_CACHE_TAGS); | ||||||
|         db.execSQL(CREATE_TABLE_TIMELINE_CACHE_LOGS); |         db.execSQL(CREATE_TABLE_TIMELINE_CACHE_LOGS); | ||||||
|  |         db.execSQL(CREATE_TABLE_INTENT); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | @ -295,6 +305,8 @@ public class Sqlite extends SQLiteOpenHelper { | ||||||
|                 db.execSQL(CREATE_TABLE_CACHE_TAGS); |                 db.execSQL(CREATE_TABLE_CACHE_TAGS); | ||||||
|             case 10: |             case 10: | ||||||
|                 db.execSQL(CREATE_TABLE_TIMELINE_CACHE_LOGS); |                 db.execSQL(CREATE_TABLE_TIMELINE_CACHE_LOGS); | ||||||
|  |             case 11: | ||||||
|  |                 db.execSQL(CREATE_TABLE_INTENT); | ||||||
|             default: |             default: | ||||||
|                 break; |                 break; | ||||||
|         } |         } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue