Reformat code
parent
3fb209a994
commit
4e89b101b2
|
@ -26,7 +26,8 @@ import androidx.media3.exoplayer.hls.HlsMediaSource
|
||||||
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
||||||
import gallery.memories.databinding.ActivityMainBinding
|
import gallery.memories.databinding.ActivityMainBinding
|
||||||
|
|
||||||
@UnstableApi class MainActivity : AppCompatActivity() {
|
@UnstableApi
|
||||||
|
class MainActivity : AppCompatActivity() {
|
||||||
companion object {
|
companion object {
|
||||||
val TAG = MainActivity::class.java.simpleName
|
val TAG = MainActivity::class.java.simpleName
|
||||||
}
|
}
|
||||||
|
@ -124,7 +125,10 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
private fun initializeWebView() {
|
private fun initializeWebView() {
|
||||||
// Intercept local APIs
|
// Intercept local APIs
|
||||||
binding.webview.webViewClient = object : WebViewClient() {
|
binding.webview.webViewClient = object : WebViewClient() {
|
||||||
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
|
override fun shouldOverrideUrlLoading(
|
||||||
|
view: WebView,
|
||||||
|
request: WebResourceRequest
|
||||||
|
): Boolean {
|
||||||
val pathMatches = request.url.path?.matches(memoriesRegex) == true
|
val pathMatches = request.url.path?.matches(memoriesRegex) == true
|
||||||
val hostMatches = request.url.host.equals(host)
|
val hostMatches = request.url.host.equals(host)
|
||||||
if (pathMatches && hostMatches) {
|
if (pathMatches && hostMatches) {
|
||||||
|
@ -137,7 +141,10 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
|
override fun shouldInterceptRequest(
|
||||||
|
view: WebView,
|
||||||
|
request: WebResourceRequest
|
||||||
|
): WebResourceResponse? {
|
||||||
return if (request.url.host == "127.0.0.1") {
|
return if (request.url.host == "127.0.0.1") {
|
||||||
nativex.handleRequest(request)
|
nativex.handleRequest(request)
|
||||||
} else null
|
} else null
|
||||||
|
@ -194,9 +201,11 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
host = Uri.parse(memoriesUrl).host
|
host = Uri.parse(memoriesUrl).host
|
||||||
|
|
||||||
// Set authorization header
|
// Set authorization header
|
||||||
binding.webview.loadUrl(memoriesUrl, mapOf(
|
binding.webview.loadUrl(
|
||||||
"Authorization" to authHeader
|
memoriesUrl, mapOf(
|
||||||
))
|
"Authorization" to authHeader
|
||||||
|
)
|
||||||
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +216,8 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
|
|
||||||
fun ensureStoragePermissions() {
|
fun ensureStoragePermissions() {
|
||||||
val requestPermissionLauncher = registerForActivityResult(
|
val requestPermissionLauncher = registerForActivityResult(
|
||||||
ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
ActivityResultContracts.RequestMultiplePermissions()
|
||||||
|
) { permissions ->
|
||||||
|
|
||||||
// we need all of these
|
// we need all of these
|
||||||
val isGranted = permissions.all { it.value }
|
val isGranted = permissions.all { it.value }
|
||||||
|
@ -236,10 +246,12 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
|
|
||||||
// Request media read permission
|
// Request media read permission
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
requestPermissionLauncher.launch(arrayOf(
|
requestPermissionLauncher.launch(
|
||||||
android.Manifest.permission.READ_MEDIA_IMAGES,
|
arrayOf(
|
||||||
android.Manifest.permission.READ_MEDIA_VIDEO,
|
android.Manifest.permission.READ_MEDIA_IMAGES,
|
||||||
))
|
android.Manifest.permission.READ_MEDIA_VIDEO,
|
||||||
|
)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
requestPermissionLauncher.launch(arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE))
|
requestPermissionLauncher.launch(arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE))
|
||||||
}
|
}
|
||||||
|
@ -278,7 +290,8 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
DefaultHttpDataSource.Factory()
|
DefaultHttpDataSource.Factory()
|
||||||
.setDefaultRequestProperties(mapOf("cookie" to cookies))
|
.setDefaultRequestProperties(mapOf("cookie" to cookies))
|
||||||
.setAllowCrossProtocolRedirects(true)
|
.setAllowCrossProtocolRedirects(true)
|
||||||
val dataSourceFactory = DefaultDataSource.Factory(this, httpDataSourceFactory)
|
val dataSourceFactory =
|
||||||
|
DefaultDataSource.Factory(this, httpDataSourceFactory)
|
||||||
|
|
||||||
// Check if HLS source from URI (contains .m3u8 anywhere)
|
// Check if HLS source from URI (contains .m3u8 anywhere)
|
||||||
exoPlayer.addMediaSource(
|
exoPlayer.addMediaSource(
|
||||||
|
@ -355,10 +368,15 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
// Set dark mode
|
// Set dark mode
|
||||||
setTheme(if (isDark) android.R.style.Theme_Black else android.R.style.Theme_Light)
|
setTheme(if (isDark) android.R.style.Theme_Black else android.R.style.Theme_Light)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
val appearance = WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS or WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
|
val appearance =
|
||||||
window.insetsController?.setSystemBarsAppearance(if (isDark) 0 else appearance, appearance)
|
WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS or WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
|
||||||
|
window.insetsController?.setSystemBarsAppearance(
|
||||||
|
if (isDark) 0 else appearance,
|
||||||
|
appearance
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
window.decorView.systemUiVisibility = if (isDark) 0 else View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
|
window.decorView.systemUiVisibility =
|
||||||
|
if (isDark) 0 else View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set colors
|
// Set colors
|
||||||
|
@ -390,8 +408,11 @@ import gallery.memories.databinding.ActivityMainBinding
|
||||||
|
|
||||||
// Schedule for resume if not active
|
// Schedule for resume if not active
|
||||||
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED) || force) {
|
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED) || force) {
|
||||||
mNeedRefresh = false
|
mNeedRefresh = false
|
||||||
binding.webview.evaluateJavascript("window._nc_event_bus?.emit('files:file:created')", null)
|
binding.webview.evaluateJavascript(
|
||||||
|
"window._nc_event_bus?.emit('files:file:created')",
|
||||||
|
null
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
mNeedRefresh = true
|
mNeedRefresh = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val DATABASE_NAME = "memories_room"
|
private val DATABASE_NAME = "memories_room"
|
||||||
@Volatile private var INSTANCE: AppDatabase? = null
|
@Volatile
|
||||||
|
private var INSTANCE: AppDatabase? = null
|
||||||
|
|
||||||
fun get(context: Context): AppDatabase {
|
fun get(context: Context): AppDatabase {
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gallery.memories.mapper
|
||||||
|
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
|
|
||||||
data class Bucket (
|
data class Bucket(
|
||||||
@ColumnInfo(name="bucket_id") val id: String,
|
@ColumnInfo(name = "bucket_id") val id: String,
|
||||||
@ColumnInfo(name="bucket_name") val name: String,
|
@ColumnInfo(name = "bucket_name") val name: String,
|
||||||
)
|
)
|
|
@ -2,7 +2,7 @@ package gallery.memories.mapper
|
||||||
|
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
|
|
||||||
data class Day (
|
data class Day(
|
||||||
@ColumnInfo(name="dayid") val dayId: Long,
|
@ColumnInfo(name = "dayid") val dayId: Long,
|
||||||
@ColumnInfo(name="count") val count: Long
|
@ColumnInfo(name = "count") val count: Long
|
||||||
)
|
)
|
|
@ -4,8 +4,9 @@ import org.json.JSONObject
|
||||||
|
|
||||||
class Response {
|
class Response {
|
||||||
companion object {
|
companion object {
|
||||||
val OK get(): JSONObject {
|
val OK
|
||||||
return JSONObject().put("message", "ok")
|
get(): JSONObject {
|
||||||
}
|
return JSONObject().put("message", "ok")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -28,9 +28,9 @@ class SystemImage {
|
||||||
var videoDuration = 0L
|
var videoDuration = 0L
|
||||||
|
|
||||||
val uri: Uri
|
val uri: Uri
|
||||||
get() {
|
get() {
|
||||||
return ContentUris.withAppendedId(mCollection, fileId)
|
return ContentUris.withAppendedId(mCollection, fileId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var mCollection: Uri = IMAGE_URI
|
private var mCollection: Uri = IMAGE_URI
|
||||||
|
|
||||||
|
@ -137,72 +137,77 @@ class SystemImage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val json get(): JSONObject {
|
val json
|
||||||
val obj = JSONObject()
|
get(): JSONObject {
|
||||||
.put(Fields.Photo.FILEID, fileId)
|
val obj = JSONObject()
|
||||||
.put(Fields.Photo.BASENAME, baseName)
|
.put(Fields.Photo.FILEID, fileId)
|
||||||
.put(Fields.Photo.MIMETYPE, mimeType)
|
.put(Fields.Photo.BASENAME, baseName)
|
||||||
.put(Fields.Photo.HEIGHT, height)
|
.put(Fields.Photo.MIMETYPE, mimeType)
|
||||||
.put(Fields.Photo.WIDTH, width)
|
.put(Fields.Photo.HEIGHT, height)
|
||||||
.put(Fields.Photo.SIZE, size)
|
.put(Fields.Photo.WIDTH, width)
|
||||||
.put(Fields.Photo.ETAG, mtime.toString())
|
.put(Fields.Photo.SIZE, size)
|
||||||
.put(Fields.Photo.EPOCH, epoch)
|
.put(Fields.Photo.ETAG, mtime.toString())
|
||||||
.put(Fields.Photo.AUID, auid)
|
.put(Fields.Photo.EPOCH, epoch)
|
||||||
|
.put(Fields.Photo.AUID, auid)
|
||||||
|
|
||||||
if (isVideo) {
|
if (isVideo) {
|
||||||
obj.put(Fields.Photo.ISVIDEO, 1)
|
obj.put(Fields.Photo.ISVIDEO, 1)
|
||||||
.put(Fields.Photo.VIDEO_DURATION, videoDuration / 1000)
|
.put(Fields.Photo.VIDEO_DURATION, videoDuration / 1000)
|
||||||
}
|
|
||||||
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
|
|
||||||
val epoch get(): Long {
|
|
||||||
return dateTaken / 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
val utcDate get(): Long {
|
|
||||||
// Get EXIF date using ExifInterface if image
|
|
||||||
if (!isVideo) {
|
|
||||||
try {
|
|
||||||
val exif = ExifInterface(dataPath)
|
|
||||||
val exifDate = exif.getAttribute(ExifInterface.TAG_DATETIME)
|
|
||||||
?: throw IOException()
|
|
||||||
val sdf = SimpleDateFormat("yyyy:MM:dd HH:mm:ss")
|
|
||||||
sdf.timeZone = TimeZone.GMT_ZONE
|
|
||||||
sdf.parse(exifDate).let {
|
|
||||||
return it.time / 1000
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "Failed to read EXIF data: " + e.message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
// No way to get the actual local date, so just assume current timezone
|
val epoch
|
||||||
return (dateTaken + TimeZone.getDefault().getOffset(dateTaken).toLong()) / 1000
|
get(): Long {
|
||||||
}
|
return dateTaken / 1000
|
||||||
|
}
|
||||||
|
|
||||||
val auid get(): Long {
|
val utcDate
|
||||||
val crc = java.util.zip.CRC32()
|
get(): Long {
|
||||||
|
// Get EXIF date using ExifInterface if image
|
||||||
|
if (!isVideo) {
|
||||||
|
try {
|
||||||
|
val exif = ExifInterface(dataPath)
|
||||||
|
val exifDate = exif.getAttribute(ExifInterface.TAG_DATETIME)
|
||||||
|
?: throw IOException()
|
||||||
|
val sdf = SimpleDateFormat("yyyy:MM:dd HH:mm:ss")
|
||||||
|
sdf.timeZone = TimeZone.GMT_ZONE
|
||||||
|
sdf.parse(exifDate).let {
|
||||||
|
return it.time / 1000
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to read EXIF data: " + e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// pass date taken + size as decimal string
|
// No way to get the actual local date, so just assume current timezone
|
||||||
crc.update((epoch.toString() + size.toString()).toByteArray())
|
return (dateTaken + TimeZone.getDefault().getOffset(dateTaken).toLong()) / 1000
|
||||||
|
}
|
||||||
|
|
||||||
return crc.value
|
val auid
|
||||||
}
|
get(): Long {
|
||||||
|
val crc = java.util.zip.CRC32()
|
||||||
|
|
||||||
val photo get(): Photo {
|
// pass date taken + size as decimal string
|
||||||
val dateCache = utcDate
|
crc.update((epoch.toString() + size.toString()).toByteArray())
|
||||||
return Photo(
|
|
||||||
localId = fileId,
|
return crc.value
|
||||||
auid = auid,
|
}
|
||||||
mtime = mtime,
|
|
||||||
dateTaken = dateCache,
|
val photo
|
||||||
dayId = dateCache / 86400,
|
get(): Photo {
|
||||||
baseName = baseName,
|
val dateCache = utcDate
|
||||||
bucketId = bucketId,
|
return Photo(
|
||||||
bucketName = bucketName,
|
localId = fileId,
|
||||||
flag = 0,
|
auid = auid,
|
||||||
)
|
mtime = mtime,
|
||||||
}
|
dateTaken = dateCache,
|
||||||
|
dayId = dateCache / 86400,
|
||||||
|
baseName = baseName,
|
||||||
|
bucketId = bucketId,
|
||||||
|
bucketName = bucketName,
|
||||||
|
flag = 0,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -17,7 +17,8 @@ import okhttp3.Response
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.net.SocketTimeoutException
|
import java.net.SocketTimeoutException
|
||||||
|
|
||||||
@UnstableApi class AccountService(private val mCtx: MainActivity) {
|
@UnstableApi
|
||||||
|
class AccountService(private val mCtx: MainActivity) {
|
||||||
companion object {
|
companion object {
|
||||||
val TAG = AccountService::class.java.simpleName
|
val TAG = AccountService::class.java.simpleName
|
||||||
}
|
}
|
||||||
|
@ -89,7 +90,8 @@ import java.net.SocketTimeoutException
|
||||||
}
|
}
|
||||||
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
val rbody = "token=$pollToken".toRequestBody("application/x-www-form-urlencoded".toMediaTypeOrNull())
|
val rbody =
|
||||||
|
"token=$pollToken".toRequestBody("application/x-www-form-urlencoded".toMediaTypeOrNull())
|
||||||
var pollCount = 0
|
var pollCount = 0
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
|
@ -12,14 +12,18 @@ class ConfigService(private val mCtx: Context) {
|
||||||
get() {
|
get() {
|
||||||
if (mEnabledBuckets != null) return mEnabledBuckets!!
|
if (mEnabledBuckets != null) return mEnabledBuckets!!
|
||||||
mEnabledBuckets = mCtx.getSharedPreferences(mCtx.getString(R.string.preferences_key), 0)
|
mEnabledBuckets = mCtx.getSharedPreferences(mCtx.getString(R.string.preferences_key), 0)
|
||||||
.getStringSet(mCtx.getString(R.string.preferences_enabled_local_folders), null)?.toList()
|
.getStringSet(mCtx.getString(R.string.preferences_enabled_local_folders), null)
|
||||||
?: listOf()
|
?.toList()
|
||||||
|
?: listOf()
|
||||||
return mEnabledBuckets!!
|
return mEnabledBuckets!!
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
mEnabledBuckets = value
|
mEnabledBuckets = value
|
||||||
mCtx.getSharedPreferences(mCtx.getString(R.string.preferences_key), 0).edit()
|
mCtx.getSharedPreferences(mCtx.getString(R.string.preferences_key), 0).edit()
|
||||||
.putStringSet(mCtx.getString(R.string.preferences_enabled_local_folders), value.toSet())
|
.putStringSet(
|
||||||
|
mCtx.getString(R.string.preferences_enabled_local_folders),
|
||||||
|
value.toSet()
|
||||||
|
)
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -44,7 +44,10 @@ class DownloadService(private val mActivity: AppCompatActivity) {
|
||||||
request.addRequestHeader("cookie", cookies)
|
request.addRequestHeader("cookie", cookies)
|
||||||
if (filename != "") {
|
if (filename != "") {
|
||||||
// Save the file to external storage
|
// Save the file to external storage
|
||||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "memories/$filename")
|
request.setDestinationInExternalPublicDir(
|
||||||
|
Environment.DIRECTORY_DOWNLOADS,
|
||||||
|
"memories/$filename"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the download
|
// Start the download
|
||||||
|
@ -92,7 +95,8 @@ class DownloadService(private val mActivity: AppCompatActivity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDownloadedFileURI(downloadId: Long): String? {
|
private fun getDownloadedFileURI(downloadId: Long): String? {
|
||||||
val downloadManager = mActivity.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
val downloadManager =
|
||||||
|
mActivity.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||||
val query = DownloadManager.Query()
|
val query = DownloadManager.Query()
|
||||||
query.setFilterById(downloadId)
|
query.setFilterById(downloadId)
|
||||||
val cursor = downloadManager.query(query)
|
val cursor = downloadManager.query(query)
|
||||||
|
|
|
@ -14,7 +14,10 @@ class ImageService(private val mCtx: Context) {
|
||||||
val bitmap =
|
val bitmap =
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
mCtx.contentResolver.loadThumbnail(
|
mCtx.contentResolver.loadThumbnail(
|
||||||
ContentUris.withAppendedId(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), id),
|
ContentUris.withAppendedId(
|
||||||
|
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL),
|
||||||
|
id
|
||||||
|
),
|
||||||
android.util.Size(2048, 2048),
|
android.util.Size(2048, 2048),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
@ -22,10 +25,10 @@ class ImageService(private val mCtx: Context) {
|
||||||
MediaStore.Images.Thumbnails.getThumbnail(
|
MediaStore.Images.Thumbnails.getThumbnail(
|
||||||
mCtx.contentResolver, id, MediaStore.Images.Thumbnails.FULL_SCREEN_KIND, null
|
mCtx.contentResolver, id, MediaStore.Images.Thumbnails.FULL_SCREEN_KIND, null
|
||||||
)
|
)
|
||||||
?: MediaStore.Video.Thumbnails.getThumbnail(
|
?: MediaStore.Video.Thumbnails.getThumbnail(
|
||||||
mCtx.contentResolver, id, MediaStore.Video.Thumbnails.FULL_SCREEN_KIND, null
|
mCtx.contentResolver, id, MediaStore.Video.Thumbnails.FULL_SCREEN_KIND, null
|
||||||
)
|
)
|
||||||
?: throw Exception("Thumbnail not found")
|
?: throw Exception("Thumbnail not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
val stream = ByteArrayOutputStream()
|
val stream = ByteArrayOutputStream()
|
||||||
|
@ -42,7 +45,7 @@ class ImageService(private val mCtx: Context) {
|
||||||
ImageDecoder.decodeBitmap(ImageDecoder.createSource(mCtx.contentResolver, uri))
|
ImageDecoder.decodeBitmap(ImageDecoder.createSource(mCtx.contentResolver, uri))
|
||||||
} else {
|
} else {
|
||||||
MediaStore.Images.Media.getBitmap(mCtx.contentResolver, uri)
|
MediaStore.Images.Media.getBitmap(mCtx.contentResolver, uri)
|
||||||
?: throw Exception("Image not found")
|
?: throw Exception("Image not found")
|
||||||
}
|
}
|
||||||
val stream = ByteArrayOutputStream()
|
val stream = ByteArrayOutputStream()
|
||||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream)
|
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream)
|
||||||
|
|
|
@ -26,7 +26,8 @@ import java.io.IOException
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
@UnstableApi class TimelineQuery(private val mCtx: MainActivity) {
|
@UnstableApi
|
||||||
|
class TimelineQuery(private val mCtx: MainActivity) {
|
||||||
private val TAG = TimelineQuery::class.java.simpleName
|
private val TAG = TimelineQuery::class.java.simpleName
|
||||||
private val mConfigService = ConfigService(mCtx)
|
private val mConfigService = ConfigService(mCtx)
|
||||||
|
|
||||||
|
@ -46,11 +47,12 @@ import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Register intent launcher for callback
|
// Register intent launcher for callback
|
||||||
deleteIntentLauncher = mCtx.registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result: ActivityResult? ->
|
deleteIntentLauncher =
|
||||||
synchronized(this) {
|
mCtx.registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result: ActivityResult? ->
|
||||||
deleteCallback?.let { it(result) }
|
synchronized(this) {
|
||||||
|
deleteCallback?.let { it(result) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initialize() {
|
fun initialize() {
|
||||||
|
@ -192,7 +194,9 @@ import java.util.concurrent.CountDownLatch
|
||||||
// Delete file with media store
|
// Delete file with media store
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
val intent = MediaStore.createTrashRequest(mCtx.contentResolver, uris, true)
|
val intent = MediaStore.createTrashRequest(mCtx.contentResolver, uris, true)
|
||||||
deleteIntentLauncher.launch(IntentSenderRequest.Builder(intent.intentSender).build())
|
deleteIntentLauncher.launch(
|
||||||
|
IntentSenderRequest.Builder(intent.intentSender).build()
|
||||||
|
)
|
||||||
|
|
||||||
// Wait for response
|
// Wait for response
|
||||||
val latch = CountDownLatch(1)
|
val latch = CountDownLatch(1)
|
||||||
|
@ -240,7 +244,7 @@ import java.util.concurrent.CountDownLatch
|
||||||
// Iterate all images and videos from system store
|
// Iterate all images and videos from system store
|
||||||
val files =
|
val files =
|
||||||
SystemImage.query(mCtx, SystemImage.IMAGE_URI, selection, selectionArgs, null) +
|
SystemImage.query(mCtx, SystemImage.IMAGE_URI, selection, selectionArgs, null) +
|
||||||
SystemImage.query(mCtx, SystemImage.VIDEO_URI, selection, selectionArgs, null)
|
SystemImage.query(mCtx, SystemImage.VIDEO_URI, selection, selectionArgs, null)
|
||||||
files.forEach { insertItemDb(it) }
|
files.forEach { insertItemDb(it) }
|
||||||
|
|
||||||
// Store last sync time
|
// Store last sync time
|
||||||
|
|
Loading…
Reference in New Issue