2018-01-04 19:52:25 +01:00
|
|
|
package jp.juggler.subwaytooter
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint
|
|
|
|
import android.content.ContentValues
|
|
|
|
import android.content.Context
|
|
|
|
import android.content.SharedPreferences
|
|
|
|
import android.database.Cursor
|
|
|
|
import android.database.sqlite.SQLiteDatabase
|
2018-09-20 18:41:04 +02:00
|
|
|
import android.net.Uri
|
2018-01-04 19:52:25 +01:00
|
|
|
import android.provider.BaseColumns
|
|
|
|
import android.util.JsonReader
|
|
|
|
import android.util.JsonToken
|
|
|
|
import android.util.JsonWriter
|
2019-01-29 02:56:24 +01:00
|
|
|
import jp.juggler.subwaytooter.api.entity.EntityId
|
2018-01-15 19:43:21 +01:00
|
|
|
import jp.juggler.subwaytooter.table.*
|
2018-12-01 00:02:18 +01:00
|
|
|
import jp.juggler.util.*
|
2018-09-20 18:41:04 +02:00
|
|
|
import org.apache.commons.io.IOUtils
|
2018-09-21 02:53:46 +02:00
|
|
|
import java.io.File
|
|
|
|
import java.io.FileOutputStream
|
|
|
|
import java.io.IOException
|
|
|
|
import java.io.InputStream
|
|
|
|
import java.util.*
|
2018-09-20 18:41:04 +02:00
|
|
|
import java.util.zip.ZipEntry
|
|
|
|
import java.util.zip.ZipOutputStream
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
object AppDataExporter {
|
|
|
|
|
|
|
|
internal val log = LogCategory("AppDataExporter")
|
|
|
|
|
|
|
|
private const val MAGIC_NAN = - 76287755398823900.0
|
|
|
|
|
|
|
|
private const val KEY_PREF = "pref"
|
|
|
|
private const val KEY_ACCOUNT = "account"
|
|
|
|
private const val KEY_COLUMN = "column"
|
|
|
|
private const val KEY_ACCT_COLOR = "acct_color"
|
|
|
|
private const val KEY_MUTED_APP = "muted_app"
|
|
|
|
private const val KEY_MUTED_WORD = "muted_word"
|
2018-03-16 11:19:27 +01:00
|
|
|
private const val KEY_FAV_MUTE = "fav_mute"
|
2019-03-13 19:11:11 +01:00
|
|
|
// v3.4.5で廃止 private const val KEY_CLIENT_INFO = "client_info2"
|
2018-01-15 19:43:21 +01:00
|
|
|
private const val KEY_HIGHLIGHT_WORD = "highlight_word"
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2020-01-07 09:03:32 +01:00
|
|
|
@Throws(IOException::class, JsonException::class)
|
2020-02-01 08:12:17 +01:00
|
|
|
private fun JsonWriter.writeJsonValue(v : Any?) {
|
|
|
|
when(v) {
|
|
|
|
null -> nullValue()
|
|
|
|
is String -> value(v)
|
|
|
|
is Boolean -> value(v)
|
|
|
|
is Number -> value(v)
|
|
|
|
is EntityId -> value(v.toString())
|
|
|
|
|
|
|
|
is JsonObject -> {
|
|
|
|
beginObject()
|
|
|
|
for(entry in v.entries) {
|
|
|
|
name(entry.key)
|
|
|
|
writeJsonValue(entry.value)
|
|
|
|
}
|
|
|
|
endObject()
|
|
|
|
}
|
|
|
|
|
|
|
|
is JsonArray -> {
|
|
|
|
beginArray()
|
|
|
|
for(value in v) {
|
|
|
|
writeJsonValue(v)
|
|
|
|
}
|
|
|
|
endArray()
|
|
|
|
}
|
|
|
|
|
|
|
|
else -> throw RuntimeException("writeJsonValue: bad value type: $v")
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-07 09:03:32 +01:00
|
|
|
@Throws(IOException::class, JsonException::class)
|
2020-02-01 08:12:17 +01:00
|
|
|
private fun JsonReader.readJsonValue() : Any? {
|
|
|
|
return when(peek()) {
|
2020-01-31 18:37:39 +01:00
|
|
|
JsonToken.NULL -> {
|
2020-02-01 08:12:17 +01:00
|
|
|
nextNull()
|
2020-01-31 18:37:39 +01:00
|
|
|
null
|
|
|
|
}
|
|
|
|
|
2020-02-01 08:12:17 +01:00
|
|
|
JsonToken.STRING -> nextString()
|
|
|
|
JsonToken.BOOLEAN -> nextBoolean()
|
|
|
|
JsonToken.NUMBER -> nextDouble()
|
|
|
|
JsonToken.BEGIN_OBJECT -> jsonObject {
|
|
|
|
beginObject()
|
|
|
|
while(hasNext()) {
|
|
|
|
val name = nextName()
|
|
|
|
val value = readJsonValue()
|
|
|
|
put(name, value)
|
|
|
|
}
|
|
|
|
endObject()
|
|
|
|
}
|
|
|
|
JsonToken.BEGIN_ARRAY -> jsonArray {
|
|
|
|
beginArray()
|
|
|
|
while(hasNext()) {
|
|
|
|
add(readJsonValue())
|
|
|
|
}
|
|
|
|
endArray()
|
|
|
|
}
|
2020-01-31 18:37:39 +01:00
|
|
|
else -> null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
@Throws(IOException::class)
|
|
|
|
private fun writeFromTable(writer : JsonWriter, json_key : String, table : String) {
|
|
|
|
|
|
|
|
writer.name(json_key)
|
|
|
|
writer.beginArray()
|
|
|
|
|
|
|
|
App1.database.query(table, null, null, null, null, null, null)?.use { cursor ->
|
|
|
|
val names = ArrayList<String>()
|
|
|
|
val column_count = cursor.columnCount
|
|
|
|
for(i in 0 until column_count) {
|
|
|
|
names.add(cursor.getColumnName(i))
|
|
|
|
}
|
|
|
|
while(cursor.moveToNext()) {
|
|
|
|
writer.beginObject()
|
|
|
|
|
|
|
|
for(i in 0 until column_count) {
|
|
|
|
when(cursor.getType(i)) {
|
|
|
|
Cursor.FIELD_TYPE_NULL -> {
|
|
|
|
writer.name(names[i])
|
|
|
|
writer.nullValue()
|
|
|
|
}
|
|
|
|
|
|
|
|
Cursor.FIELD_TYPE_INTEGER -> {
|
|
|
|
writer.name(names[i])
|
|
|
|
writer.value(cursor.getLong(i))
|
|
|
|
}
|
|
|
|
|
|
|
|
Cursor.FIELD_TYPE_STRING -> {
|
|
|
|
writer.name(names[i])
|
|
|
|
writer.value(cursor.getString(i))
|
|
|
|
}
|
|
|
|
|
|
|
|
Cursor.FIELD_TYPE_FLOAT -> {
|
|
|
|
val d = cursor.getDouble(i)
|
|
|
|
if(d.isNaN() || d.isInfinite()) {
|
|
|
|
log.w("column %s is nan or infinite value.", names[i])
|
|
|
|
} else {
|
|
|
|
writer.name(names[i])
|
|
|
|
writer.value(d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Cursor.FIELD_TYPE_BLOB -> log.w("column %s is blob.", names[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
writer.endObject()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
writer.endArray()
|
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(IOException::class)
|
|
|
|
private fun importTable(reader : JsonReader, table : String, id_map : HashMap<Long, Long>?) {
|
|
|
|
val db = App1.database
|
|
|
|
if(table == SavedAccount.table) {
|
|
|
|
SavedAccount.onDBDelete(db)
|
|
|
|
SavedAccount.onDBCreate(db)
|
|
|
|
}
|
|
|
|
|
|
|
|
db.execSQL("BEGIN TRANSACTION")
|
|
|
|
try {
|
2018-09-14 19:26:24 +02:00
|
|
|
db.execSQL("delete from $table")
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
val cv = ContentValues()
|
|
|
|
|
|
|
|
reader.beginArray()
|
|
|
|
while(reader.hasNext()) {
|
|
|
|
|
|
|
|
var old_id = - 1L
|
|
|
|
cv.clear()
|
|
|
|
|
|
|
|
reader.beginObject()
|
|
|
|
while(reader.hasNext()) {
|
|
|
|
val name = reader.nextName()
|
|
|
|
|
|
|
|
if(BaseColumns._ID == name) {
|
|
|
|
old_id = reader.nextLong()
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if(SavedAccount.table == table) {
|
|
|
|
// 一時的に存在したが現在のDBスキーマにはない項目は読み飛ばす
|
|
|
|
if("nickname" == name || "color" == name) {
|
|
|
|
reader.skipValue()
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// リアルタイム通知に関連する項目は読み飛ばす
|
|
|
|
if(SavedAccount.COL_NOTIFICATION_TAG == name
|
|
|
|
|| SavedAccount.COL_REGISTER_KEY == name
|
|
|
|
|| SavedAccount.COL_REGISTER_TIME == name) {
|
|
|
|
reader.skipValue()
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-01 08:12:17 +01:00
|
|
|
when(reader.peek()) {
|
2018-01-04 19:52:25 +01:00
|
|
|
JsonToken.NULL -> {
|
|
|
|
reader.skipValue()
|
|
|
|
cv.putNull(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
JsonToken.BOOLEAN -> cv.put(name, if(reader.nextBoolean()) 1 else 0)
|
|
|
|
|
|
|
|
JsonToken.NUMBER -> cv.put(name, reader.nextLong())
|
|
|
|
|
|
|
|
JsonToken.STRING -> cv.put(name, reader.nextString())
|
|
|
|
|
|
|
|
else -> reader.skipValue()
|
2019-08-25 10:04:34 +02:00
|
|
|
}
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
reader.endObject()
|
2018-01-21 13:46:36 +01:00
|
|
|
val new_id =
|
|
|
|
db.insertWithOnConflict(table, null, cv, SQLiteDatabase.CONFLICT_REPLACE)
|
2018-01-04 19:52:25 +01:00
|
|
|
if(new_id == - 1L) {
|
|
|
|
throw RuntimeException("importTable: invalid row_id")
|
|
|
|
}
|
|
|
|
id_map?.put(old_id, new_id)
|
|
|
|
}
|
|
|
|
reader.endArray()
|
|
|
|
db.execSQL("COMMIT TRANSACTION")
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
|
|
|
log.e(ex, "importTable failed.")
|
|
|
|
try {
|
|
|
|
db.execSQL("ROLLBACK TRANSACTION")
|
|
|
|
} catch(ignored : Throwable) {
|
|
|
|
}
|
|
|
|
|
|
|
|
throw ex
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(IOException::class)
|
|
|
|
private fun writePref(writer : JsonWriter, pref : SharedPreferences) {
|
2020-02-01 08:39:44 +01:00
|
|
|
writer.name(KEY_PREF)
|
2018-01-04 19:52:25 +01:00
|
|
|
writer.beginObject()
|
|
|
|
for((k, v) in pref.all) {
|
|
|
|
writer.name(k)
|
|
|
|
when(v) {
|
|
|
|
null -> writer.nullValue()
|
|
|
|
is String -> writer.value(v)
|
|
|
|
is Boolean -> writer.value(v)
|
|
|
|
is Number -> when {
|
|
|
|
(v is Double && v.isNaN()) -> writer.value(MAGIC_NAN)
|
|
|
|
(v is Float && v.isNaN()) -> writer.value(MAGIC_NAN)
|
|
|
|
else -> writer.value(v)
|
|
|
|
}
|
2020-02-01 08:39:44 +01:00
|
|
|
else -> error("writePref: bad data type. key=$k, type=${v.javaClass.simpleName}")
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
writer.endObject()
|
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(IOException::class)
|
|
|
|
private fun importPref(reader : JsonReader, pref : SharedPreferences) {
|
|
|
|
val e = pref.edit()
|
|
|
|
reader.beginObject()
|
|
|
|
while(reader.hasNext()) {
|
|
|
|
val k = reader.nextName() ?: throw RuntimeException("importPref: name is null")
|
2018-01-17 02:16:26 +01:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
val token = reader.peek()
|
|
|
|
if(token == JsonToken.NULL) {
|
|
|
|
reader.nextNull()
|
|
|
|
e.remove(k)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2019-08-25 10:04:34 +02:00
|
|
|
when(val prefItem = Pref.map[k]) {
|
2018-09-14 19:26:24 +02:00
|
|
|
is BooleanPref -> e.putBoolean(k, reader.nextBoolean())
|
|
|
|
is IntPref -> e.putInt(k, reader.nextInt())
|
|
|
|
is LongPref -> e.putLong(k, reader.nextLong())
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-09-14 19:26:24 +02:00
|
|
|
is StringPref -> if(prefItem.skipImport) {
|
2018-01-04 19:52:25 +01:00
|
|
|
reader.skipValue()
|
|
|
|
e.remove(k)
|
2018-01-17 02:16:26 +01:00
|
|
|
} else {
|
|
|
|
e.putString(k, reader.nextString())
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
2018-01-17 02:16:26 +01:00
|
|
|
|
2018-09-14 19:26:24 +02:00
|
|
|
is FloatPref -> {
|
2018-01-17 02:16:26 +01:00
|
|
|
val dv = reader.nextDouble()
|
|
|
|
e.putFloat(k, if(dv <= MAGIC_NAN) Float.NaN else dv.toFloat())
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
2018-01-17 02:16:26 +01:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
else -> {
|
2018-01-17 02:16:26 +01:00
|
|
|
// ignore or force reset
|
2018-01-04 19:52:25 +01:00
|
|
|
reader.skipValue()
|
|
|
|
e.remove(k)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
reader.endObject()
|
|
|
|
e.apply()
|
|
|
|
}
|
|
|
|
|
2020-01-07 09:03:32 +01:00
|
|
|
@Throws(IOException::class, JsonException::class)
|
2018-01-04 19:52:25 +01:00
|
|
|
private fun writeColumn(app_state : AppState, writer : JsonWriter) {
|
2020-02-01 08:39:44 +01:00
|
|
|
writer.name(KEY_COLUMN)
|
2018-01-04 19:52:25 +01:00
|
|
|
writer.beginArray()
|
2020-12-21 03:13:03 +01:00
|
|
|
for(column in app_state.columnList) {
|
2020-02-01 08:12:17 +01:00
|
|
|
writer.writeJsonValue(jsonObject { column.encodeJSON(this, 0) })
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
writer.endArray()
|
|
|
|
}
|
|
|
|
|
2020-01-07 09:03:32 +01:00
|
|
|
@Throws(IOException::class, JsonException::class)
|
2018-01-21 13:46:36 +01:00
|
|
|
private fun readColumn(
|
|
|
|
app_state : AppState,
|
|
|
|
reader : JsonReader,
|
|
|
|
id_map : HashMap<Long, Long>
|
2020-02-01 08:39:44 +01:00
|
|
|
) = ArrayList<Column>().also{ result->
|
2018-01-04 19:52:25 +01:00
|
|
|
reader.beginArray()
|
|
|
|
while(reader.hasNext()) {
|
2020-02-01 08:39:44 +01:00
|
|
|
val item :JsonObject = reader.readJsonValue().cast() !!
|
2019-08-25 10:04:34 +02:00
|
|
|
|
2020-02-01 08:39:44 +01:00
|
|
|
// DB上のアカウントIDが変化したので置き換える
|
2020-01-08 04:23:45 +01:00
|
|
|
when(val old_id = item.long(Column.KEY_ACCOUNT_ROW_ID) ?: - 1L) {
|
2020-02-01 08:39:44 +01:00
|
|
|
|
2020-02-01 08:12:17 +01:00
|
|
|
// 検索カラムのアカウントIDはNAアカウントと紐ついている。変換の必要はない
|
2019-08-25 10:04:34 +02:00
|
|
|
- 1L -> {
|
|
|
|
}
|
2020-02-01 08:12:17 +01:00
|
|
|
|
2020-02-01 08:39:44 +01:00
|
|
|
else -> item[Column.KEY_ACCOUNT_ROW_ID] = id_map[old_id]
|
|
|
|
?: error("readColumn: can't convert account id")
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
2020-02-01 08:12:17 +01:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
try {
|
|
|
|
result.add(Column(app_state, item))
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
|
|
|
log.e(ex, "column load failed.")
|
|
|
|
throw ex
|
|
|
|
}
|
|
|
|
}
|
|
|
|
reader.endArray()
|
|
|
|
}
|
|
|
|
|
2020-01-07 09:03:32 +01:00
|
|
|
@Throws(IOException::class, JsonException::class)
|
2018-01-04 19:52:25 +01:00
|
|
|
fun encodeAppData(context : Context, writer : JsonWriter) {
|
|
|
|
writer.setIndent(" ")
|
|
|
|
writer.beginObject()
|
|
|
|
|
|
|
|
val app_state = App1.getAppState(context)
|
2020-02-01 08:39:44 +01:00
|
|
|
|
|
|
|
writePref(writer, app_state.pref)
|
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
writeFromTable(writer, KEY_ACCOUNT, SavedAccount.table)
|
|
|
|
writeFromTable(writer, KEY_ACCT_COLOR, AcctColor.table)
|
|
|
|
writeFromTable(writer, KEY_MUTED_APP, MutedApp.table)
|
|
|
|
writeFromTable(writer, KEY_MUTED_WORD, MutedWord.table)
|
2018-03-16 11:19:27 +01:00
|
|
|
writeFromTable(writer, KEY_FAV_MUTE, FavMute.table)
|
2018-01-15 19:43:21 +01:00
|
|
|
writeFromTable(writer, KEY_HIGHLIGHT_WORD, HighlightWord.table)
|
2020-02-01 08:39:44 +01:00
|
|
|
|
|
|
|
writeColumn(app_state, writer)
|
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
writer.endObject()
|
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressLint("UseSparseArrays")
|
2020-01-07 09:03:32 +01:00
|
|
|
@Throws(IOException::class, JsonException::class)
|
2018-01-04 19:52:25 +01:00
|
|
|
internal fun decodeAppData(context : Context, reader : JsonReader) : ArrayList<Column> {
|
|
|
|
|
|
|
|
var result : ArrayList<Column>? = null
|
|
|
|
|
|
|
|
val app_state = App1.getAppState(context)
|
|
|
|
reader.beginObject()
|
|
|
|
|
|
|
|
val account_id_map = HashMap<Long, Long>()
|
|
|
|
|
|
|
|
while(reader.hasNext()) {
|
2020-02-01 08:12:17 +01:00
|
|
|
when(reader.nextName()) {
|
2018-01-17 02:16:26 +01:00
|
|
|
KEY_PREF -> importPref(reader, app_state.pref)
|
|
|
|
KEY_ACCOUNT -> importTable(reader, SavedAccount.table, account_id_map)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2018-01-17 02:16:26 +01:00
|
|
|
KEY_ACCT_COLOR -> {
|
2018-01-04 19:52:25 +01:00
|
|
|
importTable(reader, AcctColor.table, null)
|
|
|
|
AcctColor.clearMemoryCache()
|
|
|
|
}
|
|
|
|
|
2018-01-17 02:16:26 +01:00
|
|
|
KEY_MUTED_APP -> importTable(reader, MutedApp.table, null)
|
|
|
|
KEY_MUTED_WORD -> importTable(reader, MutedWord.table, null)
|
2018-03-16 11:19:27 +01:00
|
|
|
KEY_FAV_MUTE -> importTable(reader, FavMute.table, null)
|
2018-01-15 19:43:21 +01:00
|
|
|
KEY_HIGHLIGHT_WORD -> importTable(reader, HighlightWord.table, null)
|
2018-01-17 02:16:26 +01:00
|
|
|
KEY_COLUMN -> result = readColumn(app_state, reader, account_id_map)
|
2020-02-01 08:12:17 +01:00
|
|
|
|
2019-03-13 18:34:56 +01:00
|
|
|
// 端末間でクライアントIDを再利用することはできなくなった
|
|
|
|
// KEY_CLIENT_INFO -> importTable(reader, ClientInfo.table, null)
|
2020-02-01 08:12:17 +01:00
|
|
|
|
|
|
|
else -> reader.skipValue()
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
run {
|
2018-01-17 02:16:26 +01:00
|
|
|
val old_id = Pref.lpTabletTootDefaultAccount(app_state.pref)
|
2018-01-04 19:52:25 +01:00
|
|
|
if(old_id != - 1L) {
|
|
|
|
val new_id = account_id_map[old_id]
|
2018-01-17 02:16:26 +01:00
|
|
|
app_state.pref.edit().put(Pref.lpTabletTootDefaultAccount, new_id ?: - 1L).apply()
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(result == null) {
|
|
|
|
throw RuntimeException("import data does not includes column list!")
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2018-09-20 18:41:04 +02:00
|
|
|
fun saveBackgroundImage(
|
|
|
|
context : Context,
|
|
|
|
zipStream : ZipOutputStream,
|
|
|
|
column : Column
|
|
|
|
) {
|
|
|
|
try {
|
2018-12-01 00:02:18 +01:00
|
|
|
column.column_bg_image.mayUri()?.let { uri ->
|
2018-11-30 05:42:20 +01:00
|
|
|
context.contentResolver.openInputStream(uri).use { inStream ->
|
|
|
|
zipStream.putNextEntry(ZipEntry("background-image/${column.column_id}"))
|
|
|
|
try {
|
|
|
|
IOUtils.copy(inStream, zipStream)
|
|
|
|
} finally {
|
|
|
|
zipStream.closeEntry()
|
|
|
|
}
|
2018-09-20 18:41:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-04 03:04:07 +01:00
|
|
|
private val reBackgroundImage = "background-image/(.+)".asciiPattern()
|
2018-09-21 02:53:46 +02:00
|
|
|
|
2018-09-20 18:41:04 +02:00
|
|
|
// エントリが背景画像のソレなら真を返す
|
|
|
|
// column.column_bg_image を更新する場合がある
|
|
|
|
fun restoreBackgroundImage(
|
|
|
|
context : Context,
|
|
|
|
columnList : ArrayList<Column>?,
|
|
|
|
inStream : InputStream,
|
|
|
|
entryName : String
|
2018-09-21 02:53:46 +02:00
|
|
|
) : Boolean {
|
2018-09-20 18:41:04 +02:00
|
|
|
|
|
|
|
// entryName がバックグラウンド画像のそれと一致するか
|
2019-08-25 10:04:34 +02:00
|
|
|
val m = reBackgroundImage.matcher(entryName)
|
2018-09-21 02:53:46 +02:00
|
|
|
if(! m.find()) return false
|
2018-09-20 18:41:04 +02:00
|
|
|
|
|
|
|
try {
|
2019-09-12 16:05:18 +02:00
|
|
|
val id = m.groupEx(1)
|
2018-09-21 02:53:46 +02:00
|
|
|
val column = columnList?.find { it.column_id == id }
|
|
|
|
if(column == null) {
|
|
|
|
log.e("missing column for id $id")
|
|
|
|
} else {
|
|
|
|
val backgroundDir = Column.getBackgroundImageDir(context)
|
|
|
|
val file =
|
|
|
|
File(backgroundDir, "${column.column_id}:${System.currentTimeMillis()}")
|
|
|
|
FileOutputStream(file).use { outStream ->
|
|
|
|
IOUtils.copy(inStream, outStream)
|
2018-09-20 18:41:04 +02:00
|
|
|
}
|
2018-09-21 02:53:46 +02:00
|
|
|
column.column_bg_image = Uri.fromFile(file).toString()
|
2018-09-20 18:41:04 +02:00
|
|
|
}
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
log.trace(ex)
|
|
|
|
}
|
2018-09-21 02:53:46 +02:00
|
|
|
|
2018-09-20 18:41:04 +02:00
|
|
|
return true
|
|
|
|
}
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|