diff --git a/core/i18n/src/main/res/values-th/strings.xml b/core/i18n/src/main/res/values-th/strings.xml
index fe0df3d75..0557ba4f8 100644
--- a/core/i18n/src/main/res/values-th/strings.xml
+++ b/core/i18n/src/main/res/values-th/strings.xml
@@ -115,7 +115,7 @@
หาปฏิทินไม่เจอหรือ\?
คุณต้องอนุญาตให้แอปเข้าถึงปฏิทินเพื่อแสดงนัดหมายและกิจกรรมที่นี่
คุณต้องอนุญาตให้แอปเข้าถึงรายชื่อผู้ติดต่อเพื่อค้นหาในรายชื่อผู้ติดต่อ
- กำหนดให้แอป %1$s เป็นตัวใช้งานเริ่มต้นเพื่อค้นหาทางลัดแอป
+ กำหนดให้แอป %1$s เป็นลอนเชอร์เริ่มต้นเพื่อค้นหาทางลัดแอป
อนุญาต
ลักษณะ
มืด
@@ -215,7 +215,7 @@
ค้นหา
ไฟล์เก็บข้อมูลกิจกรรมแอป
รายการโปรด
- การค้นหา แท็ก สิ่งที่ถูกซ่อน
+ การค้นหา แท็ก ผลการค้นหาที่ถูกตัดออก
ไฟล์
ปฏิทิน
ทางลัดแอป
@@ -236,9 +236,9 @@
สี
เปิดคีย์บอร์ด
เปิดแอปเมื่อกด Enter
- ซ่อนผลการค้นหา
- จัดการแอปและผลการค้นหาที่ถูกซ่อน
- แสดงปุ่มที่เปิดเผยผลการค้นหาที่ซ่อนไว้
+ ผลการค้นหาที่ถูกตัดออก
+ จัดการแอปและผลการค้นหาที่ถูกตัดออก
+ แสดงปุ่มเผยผลการค้นหาที่ถูกตัดออก
แท็ก
จัดการแท็ก และสิ่งที่ถูกแท็ก
ลิงก์วิกิพีเดีย
@@ -261,7 +261,7 @@
งาน
ไม่มีสิ่งที่มีแท็กนี้
จำนวนแถว
- ควิกแอ็กชั่น
+ ควิกแอกชัน
โทร
ส่งข้อความ
ส่งอีเมล
@@ -294,10 +294,10 @@
แตะสองครั้งติดกัน
ปุ่มหน้าแรก/ท่าทางการสัมผัส
ไม่ต้องทำอะไร
- เปิดการค้นหา
+ การค้นหา / ลิ้นชักรวมแอป
ปิดหน้าจอ
- แสดงเมนูเปิดปิดเครื่อง
- เปิดแอปที่เพิ่งถูกใช้
+ เมนูเปิดปิดเครื่อง
+ แอปที่เปิดล่าสุด
เปลี่ยนช้า
เปลี่ยนปานกลาง
เปลี่ยนเร็ว
@@ -360,17 +360,17 @@
https://www.youtube.com/results\?search_query=${1}
ข้อมูลสำรอง %1$s
Google Play
- ลบรายการที่เสียและไม่จำเป็นออกจากฐานข้อมูลของแอปหน้าแรก
+ ลบรายการที่เสียและไม่จำเป็นออกจากฐานข้อมูลของลอนเชอร์
https://play.google.com/store/search\?q=${1}
- ส่งออกและนำเข้าข้อมูลแอปหน้าแรก
- ส่งออกการตั้งค่าและข้อมูลแอปหน้าแรก
- จำเป็นต้องเปิดใช้งานสิทธิ์การเข้าถึงของแอปหน้าแรกจึงจะสามารถดำเนินการนี้ได้
+ ส่งออกและนำเข้าข้อมูลลอนเชอร์
+ ส่งออกการตั้งค่าและข้อมูลลอนเชอร์
+ จำเป็นต้องเปิดใช้งานสิทธิ์การเข้าถึงของลอนเชอร์จึงจะสามารถดำเนินการนี้ได้
เข้ารหัสแบบเปอร์เซ็นต์
- การดำเนินการนี้ต้องการสิทธิ์การเข้าถึงของแอปหน้าแรก
+ การดำเนินการนี้ต้องการสิทธิ์การเข้าถึงของลอนเชอร์
application/x-www-form-urlencoded
แก้ไขวิดเจ็ต
- ไม่สามารถอ่านไฟล์โน้ตต้นฉบับได้ ข้อมูลสำเนาถูกกู้คืนมาจากพื้นที่จัดเก็บภายในของแอปหน้าแรก ถ้าคุณแก้ไขโน้ต ไฟล์โน้ตต้นฉบับอาจโดนเขียนทับ
- ไม่สามารถเขียนโน้ตไปยังไฟล์ต้นฉบับได้ บันทึกข้อมูลสำเนาไปยังพื้นที่จัดเก็บภายในของแอปหน้าแรกแล้ว
+ ไม่สามารถอ่านไฟล์โน้ตต้นฉบับได้ ข้อมูลสำเนาถูกกู้คืนมาจากพื้นที่จัดเก็บภายในของลอนเชอร์ ถ้าคุณแก้ไขโน้ต ไฟล์โน้ตต้นฉบับอาจโดนเขียนทับ
+ ไม่สามารถเขียนโน้ตไปยังไฟล์ต้นฉบับได้ บันทึกข้อมูลสำเนาไปยังพื้นที่จัดเก็บภายในของลอนเชอร์แล้ว
ลิงก์ %1$s
เพิ่มวิดเจ็ต
ปักหมุดไปยังรายการโปรด
@@ -456,7 +456,7 @@
คุณต้องอนุญาตให้แอปเข้าถึงรายชื่อผู้ติดต่อเพื่อค้นหาผู้ติดต่อ
ดูและส่งออกไฟล์เก็บข้อมูลกิจกรรมแอป
คุณต้องอนุญาตให้แอปเข้าถึงปฏิทินเพื่อค้นหาปฏิทิน
- คุณต้องกำหนดให้แอป %1$s เป็นตัวใช้งานเริ่มต้นจึงจะค้นหาทางลัดแอปได้
+ คุณต้องกำหนดให้แอป %1$s เป็นลอนเชอร์เริ่มต้นจึงจะค้นหาทางลัดแอปได้
แสดงสิ่งที่ถูกปักหมุดและสิ่งที่ถูกใช้งานบ่อยข้างบนลิ้นชักแอป
แสดงปุ่มสำหรับการเพิ่ม ลบ และจัดเรียงวิดเจ็ต
คุณต้องอนุญาตให้แอปเข้าถึงพื้นที่จัดเก็บข้อมูลภายนอกเพื่อค้นหาไฟล์บนอุปกรณ์นี้
@@ -473,7 +473,7 @@
สภาพอากาศ
คุณต้องอนุญาตให้แอปเข้าถึงพื้นที่จัดเก็บข้อมูลเพื่อค้นหาไฟล์บนอุปกรณ์นี้
คำนวณและดำเนินการทางคณิตศาสตร์
- กำหนดให้แอป %1$s เป็นตัวใช้งานเริ่มต้นเพื่อสร้างทางลัด
+ กำหนดให้แอป %1$s เป็นลอนเชอร์เริ่มต้นเพื่อสร้างทางลัด
ดาวน์โหลดอัตราแรกเปลี่ยนเพื่อแปลงสกุลเงินเป็นระยะๆ
แสดงตัวอย่างของเว็บไซต์ถ้าคำค้นหาเป็นลิงก์
ตัวควบคุมสื่อ
@@ -490,12 +490,12 @@
ข้อมูลสำรองนี้ถูกสร้างโดย %1$s คนละเวอร์ชั่น จึงไม่สามารถกู้คืนด้วยเวอร์ชั่นปัจจุบันได้
แสดงคีย์บอร์ดอัตโนมัติเมื่อเปิดลิ้นชักรวมแอป
ข้อมูลสำรองนี้ถูกสร้างโดย %1$s คนละเวอร์ชั่น ข้อมูลบางส่วนอาจไม่ถูกกู้คืนอย่างถูกต้อง
- เปิดสิ่งที่ถูกไฮไลต์หรือควิกแอ็กชั่นเมื่อแตะ \"ไป\"
+ เปิดสิ่งที่ถูกไฮไลต์หรือควิกแอกชันเมื่อแตะ \"ไป\"
รายการโปรด
แสดงปุ่มเลิกซ่อน
สิ่งที่ถูกปักหมุดไว้และสิ่งที่ถูกใช้บ่อยจะถูกแสดงที่นี่
แสดงในรายการโปรด
- ปรับแต่งควิกแอ็กชั่น
+ ปรับแต่งควิกแอกชัน
ตั้งปลุก
เริ่มจับเวลา
เขียนกำหนดการกิจกรรม
@@ -518,8 +518,8 @@
ปัดขวา
แตะค้าง
เปิดแอป
- เปิดแผงการแจ้งเตือน
- เปิดการตั้งค่าลัด
+ การแจ้งเตือน
+ การตั้งค่าลัด
คุณได้ทำท่าทางการสัมผัสแบบ \"%1$s\" ซึ่งถูกกำหนดไว้ว่าให้ทำ \"%2$s\" แต่ไม่สามารถดำเนินการได้เพราะเหตุผลต่อไปนี้:
ความเร็วในการเปลี่ยนแปลงลำดับ
การ์ดพื้นหลัง
@@ -530,7 +530,7 @@
ลิงก์ใหม่
มีความขัดแย้งของข้อมูล
ไฟล์ที่ถูกลิงก์มีข้อมูลอยู่แต่เนื้อหาของไฟล์ไม่ตรงกับเวอร์ชั่นล่าสุดที่ถูกบันทึกในโน้ตนี้ คุณต้องการเก็บเวอร์ชั่นใดไว้\?
- คุณต้องการลบชุดสี %1$s ใช่หรือไม่?
+ คุณต้องการลบโทนสี %1$s ใช่หรือไม่?
ธีม %1$s
ไม่สามารถอ่านไฟล์ที่เลือกไว้ได้ กรุณาตรวจสอบว่าคุณได้เลือกไฟล์ธีมที่ถูกต้อง (*.kvtheme) และข้อมูลไฟล์ไม่เสียหาย
ความมัว
@@ -541,7 +541,7 @@
เข้าถึงไม่ได้
การจัดตำแหน่ง
ด้านล่าง
- ไม่สามารถเข้าถึงทางลัดนี้ได้ เนื่องจาก %1$s ไม่ได้ถูกตั้งเป็นแอปหน้าแรกริ่มต้น
+ ไม่สามารถเข้าถึงทางลัดนี้ได้ เนื่องจาก %1$s ไม่ได้ถูกตั้งเป็นลอนเชอร์เริ่มต้น
ส่วนไดนามิก
ปลั๊กอิน
จัดการส่วนเสริมที่ติดตั้งไว้
@@ -587,7 +587,7 @@
ขอบเขตการค้นหา
ค้นหาร้านค้าและสถานที่อื่นๆในพื้นที่ใกล้เคียง
แผนที่
- ปรับสีของแผนที่ตามโทนสีของแอปหน้าแรก
+ ปรับสีของแผนที่ตามโทนสีของลอนเชอร์
คุณต้องตั้งค่าปลั๊กอินนี้ก่อน
พายุฝนฟ้าคะนอง
สถานที่
@@ -833,12 +833,12 @@
(ไม่มีชื่อ)
ความโปร่งใส
คุณต้องการลบชุดความโปร่งใส %1$s ใช่หรือไม่?
- การจัดตัวอักษร
- คุณต้องการลบชุดการจัดตัวอักษร %1$s ใช่หรือไม่?
- ชุดแบบอักษร
+ ฟอนต์
+ คุณต้องการลบชุดฟอนต์ %1$s ใช่หรือไม่?
+ รูปแบบฟอนต์
ค่าเริ่มต้นของอุปกรณ์
ชุดแบบอักษรของอุปกรณ์
- ชุดแบบอักษรเริ่มต้นสำหรับหัวเรื่อง
+ ฟอนต์เริ่มต้นสำหรับหัวเรื่อง
ทั่วไป
โปร่งใส
สีทึบ
@@ -850,4 +850,79 @@
แฮกเกอร์สเปซ
ร้านขายเครื่องเขียน
แถวในด็อค
+ ออก
+ ยูวี %1$d
+ แอป
+ โทนสีใหม่
+ ชุดรูปร่าง
+ ชุดฟอนต์ใหม่
+ ชุดความโปร่งใสใหม่
+ เปิดใช้งานแล้ว
+ ติดตั้งแล้ว
+ จัดการโดย Smartspacer
+ แสดงไว้เสมอ
+ แสดงเมื่อเหลือน้อยหรือกำลังชาร์จอยู่
+ ไม่แสดง
+ แอป
+ แสดงแอปทั้งหมดเมื่อยังไม่ได้พิมพ์สิ่งใดในแถบการค้นหา
+ แสดงข้อมูลแอป
+ แสดงเวอร์ชันและชื่อแพ็กเกจของแอปในเมนูกดค้าง
+ การตั้งค่าสกุลเงิน
+ Smartspacer
+ Smartspacer คือแอปเสรีและโอเพนซอร์สสำหรับวิดเจ็ตข้อมูลโดยย่อ (At a Glance) คุณสามารถติดตั้งแอป Smartspacer เพื่อนำไปใช้ในโซนไดนามิกของวิดเจ็ตนาฬิกาได้
+ เปิดใช้งานการเชื่อมต่อกับ Smartspacer
+ เปิด Smartspacer
+ ฟีด
+ ผู้ให้บริการฟีด
+ ปัดไปทางขวาบนหน้าจอหลักเพื่อเปิดฟีด
+ ยังไม่ไ่ด้ติดตั้งผู้ให้บริการฟีดใด
+ พื้นที่ส่วนตัว
+ ล็อกพื้นที่ส่วนตัว
+ ปลดล็อกพื้นที่ส่วนตัว
+ ควิกแอกชันใหม่
+ แก้ไขควิกแอกชัน
+ เว้นชื่อว่างไว้ไม่ได้
+ ไอคอน
+ อีโมจิ
+ หน้าต่างๆของลอนเชอร์
+ แอกชันระบบ
+ ทางลัดและแอปต่างๆ
+ หน้าวิดเจ็ตใหม่
+ ว่าง
+ วิดเจ็ต (%1$d)
+ เลือกแอปหรือทางลัด
+ ฟีด
+ เพิ่มรูปแบบฟอนต์
+ ลบรูปแบบฟอนต์นี้
+ ภาษาและภูมิภาค
+ ภาษา หน่วยวัด และรูปแบบเวลา
+ ภาษา
+ ค่าเริ่มต้นของระบบ
+ ปิดใช้งาน
+ การพูดถึงตัวคุณ
+ กลางๆ
+ เพศหญิง
+ เพศชาย
+ ระบบการวัด
+ เมตริก
+ สหราชอาณาจักร
+ สหรัฐอเมริกา
+ การทับศัพท์ที่ต้องการใช้
+ อัตโนมัติ
+ ระบบปฏิทิน
+ ปฏิทินหลัก
+ ปฏิทินรอง
+ สกุลเงิน
+ เพิ่มสกุลเงิน
+ เลือกแท็ก
+ แท็กใหม่
+ แก้ไขแท็ก
+ ออกโดยไม่บันทึกใช่หรือไม่
+ กข
+ สยาม
+ ไทย
+ กรุงเทพฯ
+ ถนนจตุรทิศ
+ นายสมศักดิ์ ภูมิใจ\nหมายเลขบัตร 124790
+ สนับสนุนการพัฒนา
diff --git a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt
index db995b75a..7c4e61d12 100644
--- a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt
+++ b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt
@@ -23,6 +23,8 @@ import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
+import kotlinx.coroutines.currentCoroutineContext
+import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -115,62 +117,34 @@ internal class AppShortcutRepositoryImpl(
return flags
}
+ private class NormalizedShortcut(
+ val info: ShortcutInfo,
+ val normalizedLabels: List,
+ )
+
override fun search(query: String, allowNetwork: Boolean): Flow> {
if (query.length < 3) {
return flowOf(persistentListOf())
}
val normalizedQuery = stringNormalizer.normalize(query)
+ return rawShortcuts.map { shortcuts ->
+ val filtered = shortcuts.mapIndexedNotNull { index, normalized ->
+ if (index % 8 == 0) currentCoroutineContext().ensureActive()
- return combine(
- listOf(
- settings.enabled,
- permissionsManager.hasPermission(PermissionGroup.AppShortcuts),
- shortcutChangeEmitter
- )
- ) { it }
- .map { (enabled, perm, _) ->
- enabled as Boolean
- perm as Boolean
-
- if (enabled && perm) {
- val launcherApps =
- context.getSystemService() ?: return@map persistentListOf()
-
-
- val shortcutQuery = LauncherApps.ShortcutQuery()
- shortcutQuery.setQueryFlags(
- LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED or
- LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC or
- LauncherApps.ShortcutQuery.FLAG_MATCH_MANIFEST or
- LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED or
- LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER
- )
- val shortcuts = launcherApps.getShortcuts(shortcutQuery, Process.myUserHandle())
- ?.mapNotNull {
- val score = ResultScore.from(
- query = normalizedQuery,
- primaryFields = listOfNotNull(
- it.longLabel?.toString()
- ?.let { stringNormalizer.normalize(it) },
- it.shortLabel?.toString()
- ?.let { stringNormalizer.normalize(it) },
- )
- )
- if (score.score < 0.8f) return@mapNotNull null
- LauncherShortcut(
- context,
- it,
- score
- )
- } ?: emptyList()
-
- shortcuts.toImmutableList()
-
- } else {
- persistentListOf()
- }
- }.flowOn(Dispatchers.Default)
+ val score = ResultScore.from(
+ query = normalizedQuery,
+ primaryFields = normalized.normalizedLabels,
+ )
+ if (score.score < 0.8f) return@mapIndexedNotNull null
+ LauncherShortcut(
+ context,
+ normalized.info,
+ score
+ )
+ }.toImmutableList()
+ filtered
+ }.flowOn(Dispatchers.Default)
}
private val shortcutChangeEmitter = callbackFlow {
@@ -219,6 +193,45 @@ internal class AppShortcutRepositoryImpl(
}
}.shareIn(scope, SharingStarted.WhileSubscribed(500), 1)
+ private val rawShortcuts: Flow> = combine(
+ listOf(
+ settings.enabled,
+ permissionsManager.hasPermission(PermissionGroup.AppShortcuts),
+ shortcutChangeEmitter
+ )
+ ) { it }
+ .map { (enabled, perm, _) ->
+ enabled as Boolean
+ perm as Boolean
+
+ if (!enabled || !perm) return@map emptyList()
+
+ val launcherApps =
+ context.getSystemService() ?: return@map emptyList()
+
+ val shortcutQuery = LauncherApps.ShortcutQuery()
+ shortcutQuery.setQueryFlags(
+ LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED or
+ LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC or
+ LauncherApps.ShortcutQuery.FLAG_MATCH_MANIFEST or
+ LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED or
+ LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER
+ )
+ val result = launcherApps.getShortcuts(shortcutQuery, Process.myUserHandle()) ?: emptyList()
+ val normalized = result.map {
+ NormalizedShortcut(
+ info = it,
+ normalizedLabels = listOfNotNull(
+ it.longLabel?.toString()?.let { l -> stringNormalizer.normalize(l) },
+ it.shortLabel?.toString()?.let { l -> stringNormalizer.normalize(l) },
+ )
+ )
+ }
+ normalized
+ }
+ .flowOn(Dispatchers.Default)
+ .shareIn(scope, SharingStarted.Eagerly, replay = 1)
+
override suspend fun getShortcutsConfigActivities(): List {
val launcherApps = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
if (!launcherApps.hasShortcutHostPermission()) return emptyList()
diff --git a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt
index e69a06c42..edd4b036b 100644
--- a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt
+++ b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt
@@ -8,7 +8,7 @@ import org.koin.core.qualifier.named
import org.koin.dsl.module
val appShortcutsModule = module {
- factory { AppShortcutRepositoryImpl(androidContext(), get(), get(), get(), get()) }
+ single { AppShortcutRepositoryImpl(androidContext(), get(), get(), get(), get()) }
factory>(named()) { get() }
factory(named(LauncherShortcut.Domain)) { LauncherShortcutDeserializer(androidContext()) }
factory(named(LegacyShortcut.Domain)) { LegacyShortcutDeserializer(androidContext()) }