Drafts v2 (#2032)
* cleanup warnings, reorganize some code * move ComposeAutoCompleteAdapter to compose package * composeOptions doesn't need to be a class member * add DraftsActivity and DraftsViewModel * drafts * remove unnecessary Unit in ComposeViewModel * add schema/25.json * fix db migration * drafts * cleanup code * fix compose activity rotation bug * fix media descriptions getting lost when restoring a draft * improve deleting drafts * fix ComposeActivityTest * improve draft layout for almost empty drafts * reformat code * show toast when opening reply to deleted toot * improve item_draft layout
This commit is contained in:
parent
baa915a0a3
commit
940d6d395a
85 changed files with 2032 additions and 381 deletions
|
|
@ -28,9 +28,9 @@ import com.keylesspalace.tusky.components.conversation.ConversationEntity;
|
|||
* DB version & declare DAO
|
||||
*/
|
||||
|
||||
@Database(entities = {TootEntity.class, AccountEntity.class, InstanceEntity.class, TimelineStatusEntity.class,
|
||||
@Database(entities = { TootEntity.class, DraftEntity.class, AccountEntity.class, InstanceEntity.class, TimelineStatusEntity.class,
|
||||
TimelineAccountEntity.class, ConversationEntity.class
|
||||
}, version = 24)
|
||||
}, version = 25)
|
||||
public abstract class AppDatabase extends RoomDatabase {
|
||||
|
||||
public abstract TootDao tootDao();
|
||||
|
|
@ -38,6 +38,7 @@ public abstract class AppDatabase extends RoomDatabase {
|
|||
public abstract InstanceDao instanceDao();
|
||||
public abstract ConversationsDao conversationDao();
|
||||
public abstract TimelineDao timelineDao();
|
||||
public abstract DraftDao draftDao();
|
||||
|
||||
public static final Migration MIGRATION_2_3 = new Migration(2, 3) {
|
||||
@Override
|
||||
|
|
@ -46,7 +47,6 @@ public abstract class AppDatabase extends RoomDatabase {
|
|||
database.execSQL("INSERT INTO TootEntity2 SELECT * FROM TootEntity;");
|
||||
database.execSQL("DROP TABLE TootEntity;");
|
||||
database.execSQL("ALTER TABLE TootEntity2 RENAME TO TootEntity;");
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -347,4 +347,22 @@ public abstract class AppDatabase extends RoomDatabase {
|
|||
}
|
||||
};
|
||||
|
||||
public static final Migration MIGRATION_24_25 = new Migration(24, 25) {
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
database.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS `DraftEntity` (" +
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
|
||||
"`accountId` INTEGER NOT NULL, " +
|
||||
"`inReplyToId` TEXT," +
|
||||
"`content` TEXT," +
|
||||
"`contentWarning` TEXT," +
|
||||
"`sensitive` INTEGER NOT NULL," +
|
||||
"`visibility` INTEGER NOT NULL," +
|
||||
"`attachments` TEXT NOT NULL," +
|
||||
"`poll` TEXT," +
|
||||
"`failedToSend` INTEGER NOT NULL)"
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,10 +24,7 @@ import com.google.gson.reflect.TypeToken
|
|||
import com.keylesspalace.tusky.TabData
|
||||
import com.keylesspalace.tusky.components.conversation.ConversationAccountEntity
|
||||
import com.keylesspalace.tusky.createTabDataFromId
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
import com.keylesspalace.tusky.entity.Poll
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.entity.*
|
||||
import com.keylesspalace.tusky.json.SpannedTypeAdapter
|
||||
import com.keylesspalace.tusky.util.trimTrailingWhitespace
|
||||
import java.net.URLDecoder
|
||||
|
|
@ -151,4 +148,23 @@ class Converters {
|
|||
return gson.fromJson(pollJson, Poll::class.java)
|
||||
}
|
||||
|
||||
}
|
||||
@TypeConverter
|
||||
fun newPollToJson(newPoll: NewPoll?): String? {
|
||||
return gson.toJson(newPoll)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun jsonToNewPoll(newPollJson: String?): NewPoll? {
|
||||
return gson.fromJson(newPollJson, NewPoll::class.java)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun draftAttachmentListToJson(draftAttachments: List<DraftAttachment>?): String? {
|
||||
return gson.toJson(draftAttachments)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun jsonToDraftAttachmentList(draftAttachmentListJson: String?): List<DraftAttachment>? {
|
||||
return gson.fromJson(draftAttachmentListJson, object : TypeToken<List<DraftAttachment>>() {}.type)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
40
app/src/main/java/com/keylesspalace/tusky/db/DraftDao.kt
Normal file
40
app/src/main/java/com/keylesspalace/tusky/db/DraftDao.kt
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* Copyright 2020 Tusky Contributors
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Tusky 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 Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.db
|
||||
|
||||
import androidx.paging.DataSource
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
|
||||
@Dao
|
||||
interface DraftDao {
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertOrReplace(draft: DraftEntity): Completable
|
||||
|
||||
@Query("SELECT * FROM DraftEntity WHERE accountId = :accountId ORDER BY id ASC")
|
||||
fun loadDrafts(accountId: Long): DataSource.Factory<Int, DraftEntity>
|
||||
|
||||
@Query("DELETE FROM DraftEntity WHERE id = :id")
|
||||
fun delete(id: Int): Completable
|
||||
|
||||
@Query("SELECT * FROM DraftEntity WHERE id = :id")
|
||||
fun find(id: Int): Single<DraftEntity?>
|
||||
}
|
||||
55
app/src/main/java/com/keylesspalace/tusky/db/DraftEntity.kt
Normal file
55
app/src/main/java/com/keylesspalace/tusky/db/DraftEntity.kt
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* Copyright 2020 Tusky Contributors
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Tusky 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 Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.db
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Parcelable
|
||||
import androidx.core.net.toUri
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.TypeConverters
|
||||
import com.keylesspalace.tusky.entity.NewPoll
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
@Entity
|
||||
@TypeConverters(Converters::class)
|
||||
data class DraftEntity(
|
||||
@PrimaryKey(autoGenerate = true) val id: Int = 0,
|
||||
val accountId: Long,
|
||||
val inReplyToId: String?,
|
||||
val content: String?,
|
||||
val contentWarning: String?,
|
||||
val sensitive: Boolean,
|
||||
val visibility: Status.Visibility,
|
||||
val attachments: List<DraftAttachment>,
|
||||
val poll: NewPoll?,
|
||||
val failedToSend: Boolean
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
data class DraftAttachment(
|
||||
val uriString: String,
|
||||
val description: String?,
|
||||
val type: Type
|
||||
): Parcelable {
|
||||
val uri: Uri
|
||||
get() = uriString.toUri()
|
||||
|
||||
enum class Type {
|
||||
IMAGE, VIDEO, AUDIO;
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ import com.keylesspalace.tusky.entity.Status
|
|||
// Avoiding rescanning status table when accounts table changes. Recommended by Room(c).
|
||||
indices = [Index("authorServerId", "timelineUserId")]
|
||||
)
|
||||
@TypeConverters(TootEntity.Converters::class)
|
||||
@TypeConverters(Converters::class)
|
||||
data class TimelineStatusEntity(
|
||||
val serverId: String, // id never flips: we need it for sorting so it's a real id
|
||||
val url: String?,
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@
|
|||
package com.keylesspalace.tusky.db;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.OnConflictStrategy;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
|
||||
/**
|
||||
* Created by cto3543 on 28/06/2017.
|
||||
*
|
||||
|
|
@ -30,8 +30,6 @@ import java.util.List;
|
|||
|
||||
@Dao
|
||||
public interface TootDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
void insertOrReplace(TootEntity users);
|
||||
|
||||
@Query("SELECT * FROM TootEntity ORDER BY uid DESC")
|
||||
List<TootEntity> loadAll();
|
||||
|
|
@ -41,4 +39,7 @@ public interface TootDao {
|
|||
|
||||
@Query("SELECT * FROM TootEntity WHERE uid = :uid")
|
||||
TootEntity find(int uid);
|
||||
}
|
||||
|
||||
@Query("SELECT COUNT(*) FROM TootEntity")
|
||||
Observable<Integer> savedTootCount();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue