refactor!: rename extension store bridge ABI to repo across all layers

Coordinated rename of the nine store-named bridge surfaces: Go
exports (InitExtensionStoreJSON -> InitExtensionRepoJSON etc.),
method-channel strings, the Kotlin and Swift handlers, and the Dart
PlatformBridge methods. Channel strings verified 1:1 across
Dart/Kotlin/Swift; gomobile bindings match the new export names.
Android MediaStore APIs untouched. store_registry_url pref key kept
for existing users. Local Android/iOS builds need the gobackend
AAR/xcframework rebuilt; CI does this in the release workflow.
This commit is contained in:
zarzet
2026-07-14 09:09:29 +07:00
parent 2273d9ba48
commit c4e266a5b9
7 changed files with 107 additions and 107 deletions
@@ -3397,64 +3397,64 @@ class MainActivity: FlutterFragmentActivity() {
}
result.success(response)
}
"initExtensionStore" -> {
"initExtensionRepo" -> {
val cacheDir = call.argument<String>("cache_dir") ?: ""
withContext(Dispatchers.IO) {
Gobackend.initExtensionStoreJSON(cacheDir)
Gobackend.initExtensionRepoJSON(cacheDir)
}
result.success(null)
}
"setStoreRegistryUrl" -> {
"setRepoRegistryUrl" -> {
val registryUrl = call.argument<String>("registry_url") ?: ""
withContext(Dispatchers.IO) {
Gobackend.setStoreRegistryURLJSON(registryUrl)
Gobackend.setRepoRegistryURLJSON(registryUrl)
}
result.success(null)
}
"getStoreRegistryUrl" -> {
"getRepoRegistryUrl" -> {
val response = withContext(Dispatchers.IO) {
Gobackend.getStoreRegistryURLJSON()
Gobackend.getRepoRegistryURLJSON()
}
result.success(response)
}
"clearStoreRegistryUrl" -> {
"clearRepoRegistryUrl" -> {
withContext(Dispatchers.IO) {
Gobackend.clearStoreRegistryURLJSON()
Gobackend.clearRepoRegistryURLJSON()
}
result.success(null)
}
"getStoreExtensions" -> {
"getRepoExtensions" -> {
val forceRefresh = call.argument<Boolean>("force_refresh") ?: false
val response = withContext(Dispatchers.IO) {
Gobackend.getStoreExtensionsJSON(forceRefresh)
Gobackend.getRepoExtensionsJSON(forceRefresh)
}
result.success(response)
}
"searchStoreExtensions" -> {
"searchRepoExtensions" -> {
val query = call.argument<String>("query") ?: ""
val category = call.argument<String>("category") ?: ""
val response = withContext(Dispatchers.IO) {
Gobackend.searchStoreExtensionsJSON(query, category)
Gobackend.searchRepoExtensionsJSON(query, category)
}
result.success(response)
}
"getStoreCategories" -> {
"getRepoCategories" -> {
val response = withContext(Dispatchers.IO) {
Gobackend.getStoreCategoriesJSON()
Gobackend.getRepoCategoriesJSON()
}
result.success(response)
}
"downloadStoreExtension" -> {
"downloadRepoExtension" -> {
val extensionId = call.argument<String>("extension_id") ?: ""
val destDir = call.argument<String>("dest_dir") ?: ""
val response = withContext(Dispatchers.IO) {
Gobackend.downloadStoreExtensionJSON(extensionId, destDir)
Gobackend.downloadRepoExtensionJSON(extensionId, destDir)
}
result.success(response)
}
"clearStoreCache" -> {
"clearRepoCache" -> {
withContext(Dispatchers.IO) {
Gobackend.clearStoreCacheJSON()
Gobackend.clearRepoCacheJSON()
}
result.success(null)
}
+9 -9
View File
@@ -7,12 +7,12 @@ import (
"strings"
)
func InitExtensionStoreJSON(cacheDir string) error {
func InitExtensionRepoJSON(cacheDir string) error {
initExtensionRepo(cacheDir)
return nil
}
func SetStoreRegistryURLJSON(registryURL string) error {
func SetRepoRegistryURLJSON(registryURL string) error {
repo := getExtensionRepo()
if repo == nil {
return fmt.Errorf("extension repo not initialized")
@@ -31,7 +31,7 @@ func SetStoreRegistryURLJSON(registryURL string) error {
return nil
}
func ClearStoreRegistryURLJSON() error {
func ClearRepoRegistryURLJSON() error {
repo := getExtensionRepo()
if repo == nil {
return fmt.Errorf("extension repo not initialized")
@@ -42,7 +42,7 @@ func ClearStoreRegistryURLJSON() error {
return nil
}
func GetStoreRegistryURLJSON() (string, error) {
func GetRepoRegistryURLJSON() (string, error) {
repo := getExtensionRepo()
if repo == nil {
return "", fmt.Errorf("extension repo not initialized")
@@ -51,7 +51,7 @@ func GetStoreRegistryURLJSON() (string, error) {
return repo.getRegistryURL(), nil
}
func GetStoreExtensionsJSON(forceRefresh bool) (string, error) {
func GetRepoExtensionsJSON(forceRefresh bool) (string, error) {
repo := getExtensionRepo()
if repo == nil {
return "", fmt.Errorf("extension repo not initialized")
@@ -65,7 +65,7 @@ func GetStoreExtensionsJSON(forceRefresh bool) (string, error) {
return marshalJSONString(extensions)
}
func SearchStoreExtensionsJSON(query, category string) (string, error) {
func SearchRepoExtensionsJSON(query, category string) (string, error) {
repo := getExtensionRepo()
if repo == nil {
return "", fmt.Errorf("extension repo not initialized")
@@ -79,7 +79,7 @@ func SearchStoreExtensionsJSON(query, category string) (string, error) {
return marshalJSONString(extensions)
}
func GetStoreCategoriesJSON() (string, error) {
func GetRepoCategoriesJSON() (string, error) {
repo := getExtensionRepo()
if repo == nil {
return "", fmt.Errorf("extension repo not initialized")
@@ -114,7 +114,7 @@ func buildRepoExtensionDestPath(destDir, extensionID, downloadURL string) (strin
return filepath.Join(destDir, safeExtensionID+repoExtensionPackageSuffix(downloadURL)), nil
}
func DownloadStoreExtensionJSON(extensionID, destDir string) (string, error) {
func DownloadRepoExtensionJSON(extensionID, destDir string) (string, error) {
repo := getExtensionRepo()
if repo == nil {
return "", fmt.Errorf("extension repo not initialized")
@@ -137,7 +137,7 @@ func DownloadStoreExtensionJSON(extensionID, destDir string) (string, error) {
return destPath, nil
}
func ClearStoreCacheJSON() error {
func ClearRepoCacheJSON() error {
repo := getExtensionRepo()
if repo == nil {
return fmt.Errorf("extension repo not initialized")
+16 -16
View File
@@ -399,11 +399,11 @@ func TestExportsJSONWrappersAndExtensionManagerSurface(t *testing.T) {
CancelExtensionRequestJSON("req-home")
storeDir := filepath.Join(dir, "store")
if err := InitExtensionStoreJSON(storeDir); err != nil {
t.Fatalf("InitExtensionStoreJSON: %v", err)
if err := InitExtensionRepoJSON(storeDir); err != nil {
t.Fatalf("InitExtensionRepoJSON: %v", err)
}
if err := SetStoreRegistryURLJSON("https://registry.example.com/index.json"); err != nil {
t.Fatalf("SetStoreRegistryURLJSON: %v", err)
if err := SetRepoRegistryURLJSON("https://registry.example.com/index.json"); err != nil {
t.Fatalf("SetRepoRegistryURLJSON: %v", err)
}
store := getExtensionRepo()
store.cache = &repoRegistry{Extensions: []repoExtension{{
@@ -416,17 +416,17 @@ func TestExportsJSONWrappersAndExtensionManagerSurface(t *testing.T) {
DownloadURL: "https://registry.example.com/coverage.spotiflac-ext",
}}}
store.cacheTime = time.Now()
if registryURL, err := GetStoreRegistryURLJSON(); err != nil || registryURL == "" {
t.Fatalf("GetStoreRegistryURLJSON = %q/%v", registryURL, err)
if registryURL, err := GetRepoRegistryURLJSON(); err != nil || registryURL == "" {
t.Fatalf("GetRepoRegistryURLJSON = %q/%v", registryURL, err)
}
if storeJSON, err := GetStoreExtensionsJSON(false); err != nil || !strings.Contains(storeJSON, "coverage-ext") {
t.Fatalf("GetStoreExtensionsJSON = %q/%v", storeJSON, err)
if storeJSON, err := GetRepoExtensionsJSON(false); err != nil || !strings.Contains(storeJSON, "coverage-ext") {
t.Fatalf("GetRepoExtensionsJSON = %q/%v", storeJSON, err)
}
if storeJSON, err := SearchStoreExtensionsJSON("coverage", CategoryMetadata); err != nil || !strings.Contains(storeJSON, "coverage-ext") {
t.Fatalf("SearchStoreExtensionsJSON = %q/%v", storeJSON, err)
if storeJSON, err := SearchRepoExtensionsJSON("coverage", CategoryMetadata); err != nil || !strings.Contains(storeJSON, "coverage-ext") {
t.Fatalf("SearchRepoExtensionsJSON = %q/%v", storeJSON, err)
}
if catsJSON, err := GetStoreCategoriesJSON(); err != nil || !strings.Contains(catsJSON, "metadata") {
t.Fatalf("GetStoreCategoriesJSON = %q/%v", catsJSON, err)
if catsJSON, err := GetRepoCategoriesJSON(); err != nil || !strings.Contains(catsJSON, "metadata") {
t.Fatalf("GetRepoCategoriesJSON = %q/%v", catsJSON, err)
}
if dest, err := buildRepoExtensionDestPath(
dir,
@@ -449,11 +449,11 @@ func TestExportsJSONWrappersAndExtensionManagerSurface(t *testing.T) {
); err == nil {
t.Fatal("expected invalid extension id")
}
if err := ClearStoreCacheJSON(); err != nil {
t.Fatalf("ClearStoreCacheJSON: %v", err)
if err := ClearRepoCacheJSON(); err != nil {
t.Fatalf("ClearRepoCacheJSON: %v", err)
}
if err := ClearStoreRegistryURLJSON(); err != nil {
t.Fatalf("ClearStoreRegistryURLJSON: %v", err)
if err := ClearRepoRegistryURLJSON(); err != nil {
t.Fatalf("ClearRepoRegistryURLJSON: %v", err)
}
SetLibraryCoverCacheDirJSON(filepath.Join(dir, "covers"))
+18 -18
View File
@@ -1074,60 +1074,60 @@ import Gobackend
if let error = error { throw error }
return response
case "initExtensionStore":
case "initExtensionRepo":
let args = call.arguments as! [String: Any]
let cacheDir = args["cache_dir"] as! String
GobackendInitExtensionStoreJSON(cacheDir, &error)
GobackendInitExtensionRepoJSON(cacheDir, &error)
if let error = error { throw error }
return nil
case "setStoreRegistryUrl":
case "setRepoRegistryUrl":
let args = call.arguments as! [String: Any]
let registryUrl = args["registry_url"] as? String ?? ""
GobackendSetStoreRegistryURLJSON(registryUrl, &error)
GobackendSetRepoRegistryURLJSON(registryUrl, &error)
if let error = error { throw error }
return nil
case "getStoreRegistryUrl":
let response = GobackendGetStoreRegistryURLJSON(&error)
case "getRepoRegistryUrl":
let response = GobackendGetRepoRegistryURLJSON(&error)
if let error = error { throw error }
return response
case "clearStoreRegistryUrl":
GobackendClearStoreRegistryURLJSON(&error)
case "clearRepoRegistryUrl":
GobackendClearRepoRegistryURLJSON(&error)
if let error = error { throw error }
return nil
case "getStoreExtensions":
case "getRepoExtensions":
let args = call.arguments as! [String: Any]
let forceRefresh = args["force_refresh"] as? Bool ?? false
let response = GobackendGetStoreExtensionsJSON(forceRefresh, &error)
let response = GobackendGetRepoExtensionsJSON(forceRefresh, &error)
if let error = error { throw error }
return response
case "searchStoreExtensions":
case "searchRepoExtensions":
let args = call.arguments as! [String: Any]
let query = args["query"] as? String ?? ""
let category = args["category"] as? String ?? ""
let response = GobackendSearchStoreExtensionsJSON(query, category, &error)
let response = GobackendSearchRepoExtensionsJSON(query, category, &error)
if let error = error { throw error }
return response
case "getStoreCategories":
let response = GobackendGetStoreCategoriesJSON(&error)
case "getRepoCategories":
let response = GobackendGetRepoCategoriesJSON(&error)
if let error = error { throw error }
return response
case "downloadStoreExtension":
case "downloadRepoExtension":
let args = call.arguments as! [String: Any]
let extensionId = args["extension_id"] as! String
let destDir = args["dest_dir"] as! String
let response = GobackendDownloadStoreExtensionJSON(extensionId, destDir, &error)
let response = GobackendDownloadRepoExtensionJSON(extensionId, destDir, &error)
if let error = error { throw error }
return response
case "clearStoreCache":
GobackendClearStoreCacheJSON(&error)
case "clearRepoCache":
GobackendClearRepoCacheJSON(&error)
if let error = error { throw error }
return nil
+6 -6
View File
@@ -1450,14 +1450,14 @@ class ExtensionNotifier extends Notifier<ExtensionState> {
if (ext == null) {
final cacheDir = await getTemporaryDirectory();
await PlatformBridge.initExtensionStore(cacheDir.path);
await PlatformBridge.initExtensionRepo(cacheDir.path);
final tempRoot = await getTemporaryDirectory();
final installDir = await Directory(
'${tempRoot.path}/spotiflac_bootstrap_spotify_web',
).create(recursive: true);
final downloadPath = await PlatformBridge.downloadStoreExtension(
final downloadPath = await PlatformBridge.downloadRepoExtension(
_spotifyWebExtensionId,
installDir.path,
);
@@ -1804,7 +1804,7 @@ class ExtensionNotifier extends Notifier<ExtensionState> {
String registryUrl = '';
try {
registryUrl = await PlatformBridge.getStoreRegistryUrl();
registryUrl = await PlatformBridge.getRepoRegistryUrl();
} catch (_) {}
List<Map<String, dynamic>> installed;
@@ -1877,9 +1877,9 @@ class ExtensionNotifier extends Notifier<ExtensionState> {
destDir = await Directory(
'${tmp.path}/spotiflac_restore_ext',
).create(recursive: true);
await PlatformBridge.initExtensionStore(destDir.path);
await PlatformBridge.initExtensionRepo(destDir.path);
if (registryUrl.isNotEmpty) {
await PlatformBridge.setStoreRegistryUrl(registryUrl);
await PlatformBridge.setRepoRegistryUrl(registryUrl);
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_storeRegistryUrlPrefKey, registryUrl);
}
@@ -1910,7 +1910,7 @@ class ExtensionNotifier extends Notifier<ExtensionState> {
continue;
}
try {
final path = await PlatformBridge.downloadStoreExtension(
final path = await PlatformBridge.downloadRepoExtension(
id,
destDir.path,
);
+11 -11
View File
@@ -239,10 +239,10 @@ class RepoNotifier extends Notifier<RepoState> {
);
try {
await PlatformBridge.initExtensionStore(cacheDir);
await PlatformBridge.initExtensionRepo(cacheDir);
if (savedUrl.isNotEmpty) {
await PlatformBridge.setStoreRegistryUrl(savedUrl);
await PlatformBridge.setRepoRegistryUrl(savedUrl);
await refresh();
}
@@ -267,13 +267,13 @@ class RepoNotifier extends Notifier<RepoState> {
final previousUrl = state.registryUrl;
try {
await PlatformBridge.setStoreRegistryUrl(trimmed);
await PlatformBridge.setRepoRegistryUrl(trimmed);
final resolvedUrl = await PlatformBridge.getStoreRegistryUrl();
final resolvedUrl = await PlatformBridge.getRepoRegistryUrl();
// Validate the registry actually loads before persisting the URL, so a
// broken link never survives an app restart (or a backup restore).
final extensions = await PlatformBridge.getStoreExtensions(
final extensions = await PlatformBridge.getRepoExtensions(
forceRefresh: true,
);
@@ -291,9 +291,9 @@ class RepoNotifier extends Notifier<RepoState> {
_log.e('Failed to set registry URL: $e');
try {
if (previousUrl.isNotEmpty) {
await PlatformBridge.setStoreRegistryUrl(previousUrl);
await PlatformBridge.setRepoRegistryUrl(previousUrl);
} else {
await PlatformBridge.clearStoreRegistryUrl();
await PlatformBridge.clearRepoRegistryUrl();
}
} catch (restoreError) {
_log.w('Failed to restore previous registry URL: $restoreError');
@@ -307,7 +307,7 @@ class RepoNotifier extends Notifier<RepoState> {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_registryUrlPrefKey);
await PlatformBridge.clearStoreRegistryUrl();
await PlatformBridge.clearRepoRegistryUrl();
state = state.copyWith(
registryUrl: '',
@@ -328,7 +328,7 @@ class RepoNotifier extends Notifier<RepoState> {
state = state.copyWith(isLoading: true, clearError: true);
try {
final extensions = await PlatformBridge.getStoreExtensions(
final extensions = await PlatformBridge.getRepoExtensions(
forceRefresh: forceRefresh,
);
state = state.copyWith(
@@ -381,7 +381,7 @@ class RepoNotifier extends Notifier<RepoState> {
try {
_log.i('Downloading extension: $extensionId');
final downloadPath = await PlatformBridge.downloadStoreExtension(
final downloadPath = await PlatformBridge.downloadRepoExtension(
extensionId,
tempDir,
);
@@ -426,7 +426,7 @@ class RepoNotifier extends Notifier<RepoState> {
try {
_log.i('Downloading update for: $extensionId');
final downloadPath = await PlatformBridge.downloadStoreExtension(
final downloadPath = await PlatformBridge.downloadRepoExtension(
extensionId,
tempDir,
);
+29 -29
View File
@@ -2103,71 +2103,71 @@ class PlatformBridge {
return _decodeMapListResult(result, 'getPostProcessingProviders');
}
static Future<void> initExtensionStore(String cacheDir) async {
_log.d('initExtensionStore: $cacheDir');
await _channel.invokeMethod('initExtensionStore', {'cache_dir': cacheDir});
static Future<void> initExtensionRepo(String cacheDir) async {
_log.d('initExtensionRepo: $cacheDir');
await _channel.invokeMethod('initExtensionRepo', {'cache_dir': cacheDir});
}
static Future<void> setStoreRegistryUrl(String registryUrl) async {
_log.d('setStoreRegistryUrl: $registryUrl');
await _channel.invokeMethod('setStoreRegistryUrl', {
static Future<void> setRepoRegistryUrl(String registryUrl) async {
_log.d('setRepoRegistryUrl: $registryUrl');
await _channel.invokeMethod('setRepoRegistryUrl', {
'registry_url': registryUrl,
});
}
static Future<String> getStoreRegistryUrl() async {
_log.d('getStoreRegistryUrl');
final result = await _channel.invokeMethod('getStoreRegistryUrl');
static Future<String> getRepoRegistryUrl() async {
_log.d('getRepoRegistryUrl');
final result = await _channel.invokeMethod('getRepoRegistryUrl');
return result as String? ?? '';
}
static Future<void> clearStoreRegistryUrl() async {
_log.d('clearStoreRegistryUrl');
await _channel.invokeMethod('clearStoreRegistryUrl');
static Future<void> clearRepoRegistryUrl() async {
_log.d('clearRepoRegistryUrl');
await _channel.invokeMethod('clearRepoRegistryUrl');
}
static Future<List<Map<String, dynamic>>> getStoreExtensions({
static Future<List<Map<String, dynamic>>> getRepoExtensions({
bool forceRefresh = false,
}) async {
_log.d('getStoreExtensions (forceRefresh: $forceRefresh)');
final result = await _channel.invokeMethod('getStoreExtensions', {
_log.d('getRepoExtensions (forceRefresh: $forceRefresh)');
final result = await _channel.invokeMethod('getRepoExtensions', {
'force_refresh': forceRefresh,
});
return _decodeMapListResult(result, 'getStoreExtensions');
return _decodeMapListResult(result, 'getRepoExtensions');
}
static Future<List<Map<String, dynamic>>> searchStoreExtensions(
static Future<List<Map<String, dynamic>>> searchRepoExtensions(
String query, {
String? category,
}) async {
_log.d('searchStoreExtensions: "$query" (category: $category)');
final result = await _channel.invokeMethod('searchStoreExtensions', {
_log.d('searchRepoExtensions: "$query" (category: $category)');
final result = await _channel.invokeMethod('searchRepoExtensions', {
'query': query,
'category': category ?? '',
});
return _decodeMapListResult(result, 'searchStoreExtensions');
return _decodeMapListResult(result, 'searchRepoExtensions');
}
static Future<List<String>> getStoreCategories() async {
final result = await _channel.invokeMethod('getStoreCategories');
return _decodeStringListResult(result, 'getStoreCategories');
static Future<List<String>> getRepoCategories() async {
final result = await _channel.invokeMethod('getRepoCategories');
return _decodeStringListResult(result, 'getRepoCategories');
}
static Future<String> downloadStoreExtension(
static Future<String> downloadRepoExtension(
String extensionId,
String destDir,
) async {
_log.i('downloadStoreExtension: $extensionId to $destDir');
final result = await _channel.invokeMethod('downloadStoreExtension', {
_log.i('downloadRepoExtension: $extensionId to $destDir');
final result = await _channel.invokeMethod('downloadRepoExtension', {
'extension_id': extensionId,
'dest_dir': destDir,
});
return result as String;
}
static Future<void> clearStoreCache() async {
_log.d('clearStoreCache');
await _channel.invokeMethod('clearStoreCache');
static Future<void> clearRepoCache() async {
_log.d('clearRepoCache');
await _channel.invokeMethod('clearRepoCache');
}
static Future<Map<String, dynamic>> parseCueSheet(