From 091753634038d3021af703904324671a1cf64af3 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Fri, 28 Jul 2023 19:02:22 -0400 Subject: [PATCH 01/15] Add `ios` as target for importing messages. --- package-lock.json | 38 ++++++ package.json | 1 + .../Resources/af.lproj/Localizable.strings | 4 + .../Resources/am.lproj/Localizable.strings | 4 + .../Resources/ar.lproj/Localizable.strings | 4 + .../Resources/az.lproj/Localizable.strings | 4 + .../Resources/bg.lproj/Localizable.strings | 4 + .../Resources/bn.lproj/Localizable.strings | 4 + .../Resources/bs.lproj/Localizable.strings | 4 + .../Resources/ca.lproj/Localizable.strings | 4 + .../Resources/cs.lproj/Localizable.strings | 4 + .../Resources/da.lproj/Localizable.strings | 4 + .../Resources/de.lproj/Localizable.strings | 4 + .../Resources/el.lproj/Localizable.strings | 4 + .../Resources/en-GB.lproj/Localizable.strings | 4 + .../Resources/en.lproj/Localizable.strings | 4 + .../es-419.lproj/Localizable.strings | 4 + .../Resources/es.lproj/Localizable.strings | 4 + .../Resources/et.lproj/Localizable.strings | 4 + .../Resources/fa.lproj/Localizable.strings | 4 + .../Resources/fi.lproj/Localizable.strings | 4 + .../Resources/fil.lproj/Localizable.strings | 4 + .../Resources/fr.lproj/Localizable.strings | 4 + .../Resources/he.lproj/Localizable.strings | 4 + .../Resources/hi.lproj/Localizable.strings | 4 + .../Resources/hr.lproj/Localizable.strings | 4 + .../Resources/hu.lproj/Localizable.strings | 4 + .../Resources/hy.lproj/Localizable.strings | 4 + .../Resources/id.lproj/Localizable.strings | 4 + .../Resources/is.lproj/Localizable.strings | 4 + .../Resources/it.lproj/Localizable.strings | 4 + .../Resources/ja.lproj/Localizable.strings | 4 + .../Resources/ka.lproj/Localizable.strings | 4 + .../Resources/kk.lproj/Localizable.strings | 4 + .../Resources/km.lproj/Localizable.strings | 4 + .../Resources/ko.lproj/Localizable.strings | 4 + .../Resources/lo.lproj/Localizable.strings | 4 + .../Resources/lt.lproj/Localizable.strings | 4 + .../Resources/lv.lproj/Localizable.strings | 4 + .../Resources/mk.lproj/Localizable.strings | 4 + .../Resources/mn.lproj/Localizable.strings | 4 + .../Resources/mr.lproj/Localizable.strings | 4 + .../Resources/ms.lproj/Localizable.strings | 4 + .../Resources/my.lproj/Localizable.strings | 4 + .../Resources/ne.lproj/Localizable.strings | 4 + .../Resources/nl.lproj/Localizable.strings | 4 + .../Resources/no.lproj/Localizable.strings | 4 + .../Resources/pl.lproj/Localizable.strings | 4 + .../Resources/pt-BR.lproj/Localizable.strings | 4 + .../Resources/pt-PT.lproj/Localizable.strings | 4 + .../Resources/ro.lproj/Localizable.strings | 4 + .../Resources/ru.lproj/Localizable.strings | 4 + .../Resources/si.lproj/Localizable.strings | 4 + .../Resources/sk.lproj/Localizable.strings | 4 + .../Resources/sl.lproj/Localizable.strings | 4 + .../Resources/sq.lproj/Localizable.strings | 4 + .../sr-Latn.lproj/Localizable.strings | 4 + .../Resources/sr.lproj/Localizable.strings | 4 + .../Resources/sv.lproj/Localizable.strings | 4 + .../Resources/sw.lproj/Localizable.strings | 4 + .../Resources/ta.lproj/Localizable.strings | 4 + .../Resources/th.lproj/Localizable.strings | 4 + .../Resources/tr.lproj/Localizable.strings | 4 + .../Resources/uk.lproj/Localizable.strings | 4 + .../Resources/ur.lproj/Localizable.strings | 4 + .../Resources/vi.lproj/Localizable.strings | 4 + .../Resources/zh-CN.lproj/Localizable.strings | 4 + .../Resources/zh-TW.lproj/Localizable.strings | 4 + src/cordova/import_messages.action.mjs | 108 ++++++++++++++++-- 69 files changed, 400 insertions(+), 11 deletions(-) create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/af.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/am.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/ar.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/az.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/bg.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/bn.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/bs.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/ca.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/cs.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/da.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/de.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/el.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/en-GB.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/en.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/es-419.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/es.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/et.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/fa.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/fi.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/fil.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/fr.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/he.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/hi.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/hr.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/hu.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/hy.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/id.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/is.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/it.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/ja.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/ka.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/kk.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/km.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/ko.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/lo.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/lt.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/lv.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/mk.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/mn.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/mr.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/ms.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/my.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/ne.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/nl.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/no.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/pl.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/pt-BR.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/pt-PT.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/ro.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/ru.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/si.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/sk.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/sl.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/sq.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/sr-Latn.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/sr.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/sv.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/sw.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/ta.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/th.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/tr.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/uk.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/ur.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/vi.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/zh-CN.lproj/Localizable.strings create mode 100644 src/cordova/apple/xcode/ios/Outline/Resources/zh-TW.lproj/Localizable.strings diff --git a/package-lock.json b/package-lock.json index 929576d7ffe..5c79d23ad91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -92,6 +92,7 @@ "file-loader": "^6.2.0", "html-webpack-plugin": "^5.1.0", "husky": "^1.3.1", + "i18n-strings-files": "^2.0.0", "intl-messageformat": "^9.12.0", "istanbul": "^0.4.5", "karma": "^6.3.16", @@ -12081,6 +12082,18 @@ "which": "bin/which" } }, + "node_modules/i18n-strings-files": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/i18n-strings-files/-/i18n-strings-files-2.0.0.tgz", + "integrity": "sha512-0Ii7DcVmoPscrzDAEsIvQuBalmwkEgc60oGg8FcdMq1Da/paov0mpRZGqEnVa3Hv8hBMYmHP7JnXrB7jtB3NjA==", + "dev": true, + "dependencies": { + "iconv": "^3.0.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/icon-gen": { "version": "2.0.0", "dev": true, @@ -12099,6 +12112,16 @@ "node": ">= 8" } }, + "node_modules/iconv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/iconv/-/iconv-3.0.1.tgz", + "integrity": "sha512-lJnFLxVc0d82R7GfU7a9RujKVUQ3Eee19tPKWZWBJtAEGRHVEyFzCtbNl3GPKuDnHBBRT4/nDS4Ru9AIDT72qA==", + "dev": true, + "hasInstallScript": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/iconv-corefoundation": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", @@ -29405,6 +29428,15 @@ } } }, + "i18n-strings-files": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/i18n-strings-files/-/i18n-strings-files-2.0.0.tgz", + "integrity": "sha512-0Ii7DcVmoPscrzDAEsIvQuBalmwkEgc60oGg8FcdMq1Da/paov0mpRZGqEnVa3Hv8hBMYmHP7JnXrB7jtB3NjA==", + "dev": true, + "requires": { + "iconv": "^3.0.1" + } + }, "icon-gen": { "version": "2.0.0", "dev": true, @@ -29416,6 +29448,12 @@ "uuid": "^3.3.2" } }, + "iconv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/iconv/-/iconv-3.0.1.tgz", + "integrity": "sha512-lJnFLxVc0d82R7GfU7a9RujKVUQ3Eee19tPKWZWBJtAEGRHVEyFzCtbNl3GPKuDnHBBRT4/nDS4Ru9AIDT72qA==", + "dev": true + }, "iconv-corefoundation": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", diff --git a/package.json b/package.json index 824953b330b..d191e750278 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,7 @@ "file-loader": "^6.2.0", "html-webpack-plugin": "^5.1.0", "husky": "^1.3.1", + "i18n-strings-files": "^2.0.0", "intl-messageformat": "^9.12.0", "istanbul": "^0.4.5", "karma": "^6.3.16", diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/af.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/af.lproj/Localizable.strings new file mode 100644 index 00000000000..562cff67dc8 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/af.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Gekoppel"; +"disconnected_server_state" = "Ontkoppel"; +"tray_open_window" = "Oop"; +"quit" = "Verlaat"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/am.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/am.lproj/Localizable.strings new file mode 100644 index 00000000000..540e6c3a8da --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/am.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "ተገናኝቷል"; +"disconnected_server_state" = "ተቋርጧል"; +"tray_open_window" = "ክፈት"; +"quit" = "ጨርስ"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ar.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/ar.lproj/Localizable.strings new file mode 100644 index 00000000000..9a8e7bc75d2 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/ar.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "متصل"; +"disconnected_server_state" = "غير متصل"; +"tray_open_window" = "فتح"; +"quit" = "إنهاء"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/az.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/az.lproj/Localizable.strings new file mode 100644 index 00000000000..49462b2920a --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/az.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Qoşuldu"; +"disconnected_server_state" = "Bağlantı kəsildi"; +"tray_open_window" = "Açın"; +"quit" = "Çıxın"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/bg.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/bg.lproj/Localizable.strings new file mode 100644 index 00000000000..11fc114a561 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/bg.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Установена е връзка"; +"disconnected_server_state" = "Връзката бе прекратена"; +"tray_open_window" = "Отваряне"; +"quit" = "Излизане"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/bn.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/bn.lproj/Localizable.strings new file mode 100644 index 00000000000..912be51a14d --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/bn.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "কানেক্ট করা আছে"; +"disconnected_server_state" = "ডিসকানেক্ট হয়ে গেছে"; +"tray_open_window" = "খুলুন"; +"quit" = "বেরিয়ে আসুন"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/bs.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/bs.lproj/Localizable.strings new file mode 100644 index 00000000000..affe08c2e86 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/bs.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Povezano"; +"disconnected_server_state" = "Veza je prekinuta"; +"tray_open_window" = "Otvori"; +"quit" = "Napusti"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ca.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/ca.lproj/Localizable.strings new file mode 100644 index 00000000000..d4c7a90d86d --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/ca.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Connectat"; +"disconnected_server_state" = "Desconnectat"; +"tray_open_window" = "Obre"; +"quit" = "Surt"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/cs.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/cs.lproj/Localizable.strings new file mode 100644 index 00000000000..5cac0448d93 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/cs.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Připojeno"; +"disconnected_server_state" = "Odpojeno"; +"tray_open_window" = "Otevřít"; +"quit" = "Zavřít"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/da.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/da.lproj/Localizable.strings new file mode 100644 index 00000000000..b78d28690e3 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/da.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Tilsluttet"; +"disconnected_server_state" = "Forbindelsen er afbrudt"; +"tray_open_window" = "Åbn"; +"quit" = "Luk"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/de.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/de.lproj/Localizable.strings new file mode 100644 index 00000000000..a2ebfd64291 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/de.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Verbunden"; +"disconnected_server_state" = "Nicht verbunden"; +"tray_open_window" = "Öffnen"; +"quit" = "Beenden"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/el.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/el.lproj/Localizable.strings new file mode 100644 index 00000000000..cc0c591cb39 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/el.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Συνδεδεμένος"; +"disconnected_server_state" = "Αποσυνδεδεμένος"; +"tray_open_window" = "Άνοιγμα"; +"quit" = "Έξοδος"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/en-GB.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/en-GB.lproj/Localizable.strings new file mode 100644 index 00000000000..86f8327c400 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/en-GB.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Connected"; +"disconnected_server_state" = "Disconnected"; +"tray_open_window" = "Open"; +"quit" = "Exit"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/en.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/en.lproj/Localizable.strings new file mode 100644 index 00000000000..e6a71d09521 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/en.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Connected"; +"disconnected_server_state" = "Disconnected"; +"tray_open_window" = "Open"; +"quit" = "Quit"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/es-419.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/es-419.lproj/Localizable.strings new file mode 100644 index 00000000000..0f6d0460070 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/es-419.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Conectado"; +"disconnected_server_state" = "Desconectado"; +"tray_open_window" = "Abrir"; +"quit" = "Salir"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/es.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/es.lproj/Localizable.strings new file mode 100644 index 00000000000..a9b5eecd3e0 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/es.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Conectado"; +"disconnected_server_state" = "Desconectado"; +"tray_open_window" = "Abrir"; +"quit" = "Cerrar"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/et.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/et.lproj/Localizable.strings new file mode 100644 index 00000000000..bc4c1fbc746 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/et.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Ühendatud"; +"disconnected_server_state" = "Ühendus on katkestatud"; +"tray_open_window" = "Ava"; +"quit" = "Välju"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/fa.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/fa.lproj/Localizable.strings new file mode 100644 index 00000000000..9a2fb79ec10 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/fa.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "وصل شدید"; +"disconnected_server_state" = "اتصال قطع شد"; +"tray_open_window" = "باز کردن"; +"quit" = "خروج"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/fi.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/fi.lproj/Localizable.strings new file mode 100644 index 00000000000..cf5b9c1eb47 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/fi.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Yhdistetty"; +"disconnected_server_state" = "Yhteys katkaistu"; +"tray_open_window" = "Avaa"; +"quit" = "Sulje"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/fil.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/fil.lproj/Localizable.strings new file mode 100644 index 00000000000..b26f74cea72 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/fil.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Nakakonekta na"; +"disconnected_server_state" = "Nadiskonekta"; +"tray_open_window" = "Buksan"; +"quit" = "Umalis"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/fr.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/fr.lproj/Localizable.strings new file mode 100644 index 00000000000..8fbba6d51e8 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/fr.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Connecté"; +"disconnected_server_state" = "Déconnecté"; +"tray_open_window" = "Ouvrir"; +"quit" = "Quitter"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/he.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/he.lproj/Localizable.strings new file mode 100644 index 00000000000..8c26519c6b3 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/he.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "מחובר"; +"disconnected_server_state" = "מנותק"; +"tray_open_window" = "פתיחה"; +"quit" = "יציאה"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/hi.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/hi.lproj/Localizable.strings new file mode 100644 index 00000000000..3756f197c21 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/hi.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "कनेक्ट किया गया"; +"disconnected_server_state" = "डिसकनेक्ट किया गया"; +"tray_open_window" = "खोलें"; +"quit" = "छोड़ें"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/hr.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/hr.lproj/Localizable.strings new file mode 100644 index 00000000000..1d007082206 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/hr.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Povezano"; +"disconnected_server_state" = "Veza je prekinuta"; +"tray_open_window" = "Otvori"; +"quit" = "Zatvori"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/hu.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/hu.lproj/Localizable.strings new file mode 100644 index 00000000000..156cc4c456d --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/hu.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Csatlakoztatva"; +"disconnected_server_state" = "Leválasztva"; +"tray_open_window" = "Megnyitás"; +"quit" = "Kilépés"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/hy.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/hy.lproj/Localizable.strings new file mode 100644 index 00000000000..10433d476f8 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/hy.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Միացված է"; +"disconnected_server_state" = "Անջատված է"; +"tray_open_window" = "Բացել"; +"quit" = "Փակել"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/id.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/id.lproj/Localizable.strings new file mode 100644 index 00000000000..050c940662f --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/id.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Terhubung"; +"disconnected_server_state" = "Sambungan terputus"; +"tray_open_window" = "Buka"; +"quit" = "Tutup"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/is.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/is.lproj/Localizable.strings new file mode 100644 index 00000000000..f7a913ac6f3 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/is.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Tengt"; +"disconnected_server_state" = "Aftengt"; +"tray_open_window" = "Opna"; +"quit" = "Hætta"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/it.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/it.lproj/Localizable.strings new file mode 100644 index 00000000000..20af395b1a3 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/it.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Connesso"; +"disconnected_server_state" = "Server disconnesso"; +"tray_open_window" = "Apri"; +"quit" = "Esci"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ja.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/ja.lproj/Localizable.strings new file mode 100644 index 00000000000..ba823c0db8f --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/ja.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "接続しました"; +"disconnected_server_state" = "接続が切断されました"; +"tray_open_window" = "開く"; +"quit" = "終了"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ka.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/ka.lproj/Localizable.strings new file mode 100644 index 00000000000..36fcecd9b11 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/ka.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "დაკავშირებულია"; +"disconnected_server_state" = "კავშირი გაწყვეტილია"; +"tray_open_window" = "ღიაა"; +"quit" = "გასვლა"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/kk.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/kk.lproj/Localizable.strings new file mode 100644 index 00000000000..d27eb937240 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/kk.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Байланыс орнатылды."; +"disconnected_server_state" = "Ажыратылған"; +"tray_open_window" = "Ашу"; +"quit" = "Шығу"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/km.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/km.lproj/Localizable.strings new file mode 100644 index 00000000000..3e31bab5a72 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/km.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "បានភ្ជាប់"; +"disconnected_server_state" = "បានផ្ដាច់"; +"tray_open_window" = "បើក"; +"quit" = "ចាកចេញ"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ko.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/ko.lproj/Localizable.strings new file mode 100644 index 00000000000..06c02d33e45 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/ko.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "연결됨"; +"disconnected_server_state" = "연결 해제됨"; +"tray_open_window" = "열기"; +"quit" = "종료"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/lo.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/lo.lproj/Localizable.strings new file mode 100644 index 00000000000..c37d6edce89 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/lo.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "ເຊື່ອມຕໍ່ແລ້ວ"; +"disconnected_server_state" = "ຕັດການເຊື່ອມຕໍ່ແລ້ວ"; +"tray_open_window" = "ເປີດ"; +"quit" = "ປິດ"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/lt.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/lt.lproj/Localizable.strings new file mode 100644 index 00000000000..cdfe88b29b8 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/lt.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Prisijungta"; +"disconnected_server_state" = "Atsijungta"; +"tray_open_window" = "Atidaryti"; +"quit" = "Išeiti"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/lv.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/lv.lproj/Localizable.strings new file mode 100644 index 00000000000..1602a5a55ce --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/lv.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Savienojums izveidots"; +"disconnected_server_state" = "Savienojums pārtraukts"; +"tray_open_window" = "Atvērt"; +"quit" = "Aizvērt"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/mk.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/mk.lproj/Localizable.strings new file mode 100644 index 00000000000..a324ca21484 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/mk.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Поврзано"; +"disconnected_server_state" = "Не е поврзано"; +"tray_open_window" = "Отвори"; +"quit" = "Излези"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/mn.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/mn.lproj/Localizable.strings new file mode 100644 index 00000000000..b471f3727a5 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/mn.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Холбогдсон"; +"disconnected_server_state" = "Салсан"; +"tray_open_window" = "Нээх"; +"quit" = "Гарах"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/mr.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/mr.lproj/Localizable.strings new file mode 100644 index 00000000000..ad18d96f251 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/mr.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "कनेक्ट केले आहे"; +"disconnected_server_state" = "डिस्कनेक्ट केले"; +"tray_open_window" = "उघडा"; +"quit" = "बाहेर पडा"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ms.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/ms.lproj/Localizable.strings new file mode 100644 index 00000000000..df9d5973df9 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/ms.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Disambungkan"; +"disconnected_server_state" = "Diputuskan sambungan"; +"tray_open_window" = "Buka"; +"quit" = "Keluar"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/my.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/my.lproj/Localizable.strings new file mode 100644 index 00000000000..15ec3796f17 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/my.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "ချိတ်ဆက်ထားသည်"; +"disconnected_server_state" = "ချိတ်ဆက်မထားပါ"; +"tray_open_window" = "ဖွင့်ရန်"; +"quit" = "ထွက်ရန်"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ne.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/ne.lproj/Localizable.strings new file mode 100644 index 00000000000..74cd0ba5951 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/ne.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "कनेक्ट गरिएको छ"; +"disconnected_server_state" = "डिस्कनेक्ट गरिएको छ"; +"tray_open_window" = "खोल्नुहोस्"; +"quit" = "बाहिरिनुहोस्"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/nl.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/nl.lproj/Localizable.strings new file mode 100644 index 00000000000..1a6eb68335c --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/nl.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Verbonden"; +"disconnected_server_state" = "Verbinding verbroken"; +"tray_open_window" = "Openen"; +"quit" = "Sluiten"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/no.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/no.lproj/Localizable.strings new file mode 100644 index 00000000000..6b6f8323bf6 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/no.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Tilkoblet"; +"disconnected_server_state" = "Koblet fra"; +"tray_open_window" = "Åpne"; +"quit" = "Avslutt"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/pl.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/pl.lproj/Localizable.strings new file mode 100644 index 00000000000..c1b4ead70f2 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/pl.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Połączono"; +"disconnected_server_state" = "Odłączono"; +"tray_open_window" = "Otwórz"; +"quit" = "Zamknij"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/pt-BR.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/pt-BR.lproj/Localizable.strings new file mode 100644 index 00000000000..2f61bb2a25c --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/pt-BR.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Conectado"; +"disconnected_server_state" = "Desconectado"; +"tray_open_window" = "Abrir"; +"quit" = "Sair"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/pt-PT.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/pt-PT.lproj/Localizable.strings new file mode 100644 index 00000000000..2aa7c0cc754 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/pt-PT.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Ligado"; +"disconnected_server_state" = "Desligado"; +"tray_open_window" = "Abrir"; +"quit" = "Sair"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ro.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/ro.lproj/Localizable.strings new file mode 100644 index 00000000000..853d5a8be81 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/ro.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Conectat"; +"disconnected_server_state" = "Deconectat"; +"tray_open_window" = "Deschideți"; +"quit" = "Ieșiți"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ru.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/ru.lproj/Localizable.strings new file mode 100644 index 00000000000..a62a95aa571 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/ru.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Подключен"; +"disconnected_server_state" = "Отключен"; +"tray_open_window" = "Открыть"; +"quit" = "Выйти"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/si.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/si.lproj/Localizable.strings new file mode 100644 index 00000000000..01c358b7602 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/si.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "සම්බන්‍ධයි"; +"disconnected_server_state" = "විසන්‍ධි විය"; +"tray_open_window" = "විවෘතයි"; +"quit" = "ඉවත් වන්න"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sk.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/sk.lproj/Localizable.strings new file mode 100644 index 00000000000..5b0fa004e6f --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/sk.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Pripojené"; +"disconnected_server_state" = "Odpojené"; +"tray_open_window" = "Otvoriť"; +"quit" = "Ukončiť"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sl.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/sl.lproj/Localizable.strings new file mode 100644 index 00000000000..1e2d86f32d7 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/sl.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Povezava je vzpostavljena"; +"disconnected_server_state" = "Povezava je prekinjena"; +"tray_open_window" = "Odpri"; +"quit" = "Zapri"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sq.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/sq.lproj/Localizable.strings new file mode 100644 index 00000000000..7b50f40ee53 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/sq.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Lidhur"; +"disconnected_server_state" = "Shkëputur"; +"tray_open_window" = "Hap"; +"quit" = "Dil"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sr-Latn.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/sr-Latn.lproj/Localizable.strings new file mode 100644 index 00000000000..bde239c5a6e --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/sr-Latn.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Povezano je"; +"disconnected_server_state" = "Veza je prekinuta"; +"tray_open_window" = "Otvori"; +"quit" = "Zatvori"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sr.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/sr.lproj/Localizable.strings new file mode 100644 index 00000000000..574eb819819 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/sr.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Повезано је"; +"disconnected_server_state" = "Веза је прекинута"; +"tray_open_window" = "Отвори"; +"quit" = "Затвори"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sv.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/sv.lproj/Localizable.strings new file mode 100644 index 00000000000..e884fb1968a --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/sv.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Ansluten"; +"disconnected_server_state" = "Frånkopplad"; +"tray_open_window" = "Öppna"; +"quit" = "Avsluta"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sw.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/sw.lproj/Localizable.strings new file mode 100644 index 00000000000..cce7ce82fd9 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/sw.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Imeunganishwa"; +"disconnected_server_state" = "Imetenganishwa"; +"tray_open_window" = "Fungua"; +"quit" = "Funga"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ta.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/ta.lproj/Localizable.strings new file mode 100644 index 00000000000..f386f754f2f --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/ta.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "இணைக்கப்பட்டது"; +"disconnected_server_state" = "இணைப்பு துண்டிக்கப்பட்டது"; +"tray_open_window" = "திற"; +"quit" = "வெளியேறு"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/th.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/th.lproj/Localizable.strings new file mode 100644 index 00000000000..023a662b6ba --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/th.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "เชื่อมต่อแล้ว"; +"disconnected_server_state" = "ยกเลิกการเชื่อมต่อแล้ว"; +"tray_open_window" = "เปิด"; +"quit" = "ปิด"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/tr.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/tr.lproj/Localizable.strings new file mode 100644 index 00000000000..72c09beb528 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/tr.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Bağlanıldı"; +"disconnected_server_state" = "Bağlantı kesildi"; +"tray_open_window" = "Aç"; +"quit" = "Çık"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/uk.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/uk.lproj/Localizable.strings new file mode 100644 index 00000000000..8a107d05c91 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/uk.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Підключено"; +"disconnected_server_state" = "Відключено"; +"tray_open_window" = "Відкрити"; +"quit" = "Вийти"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ur.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/ur.lproj/Localizable.strings new file mode 100644 index 00000000000..76ac7c63d1a --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/ur.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "منسلک ہے"; +"disconnected_server_state" = "غیر منسلک ہے"; +"tray_open_window" = "کھولیں"; +"quit" = "بند کریں"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/vi.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/vi.lproj/Localizable.strings new file mode 100644 index 00000000000..c2c69cf0a9e --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/vi.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "Đã kết nối"; +"disconnected_server_state" = "Đã ngắt kết nối"; +"tray_open_window" = "Mở"; +"quit" = "Thoát"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/zh-CN.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/zh-CN.lproj/Localizable.strings new file mode 100644 index 00000000000..5ddd80cb550 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/zh-CN.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "已连接"; +"disconnected_server_state" = "已断开连接"; +"tray_open_window" = "打开"; +"quit" = "退出"; diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/zh-TW.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/zh-TW.lproj/Localizable.strings new file mode 100644 index 00000000000..47560372795 --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Resources/zh-TW.lproj/Localizable.strings @@ -0,0 +1,4 @@ +"connected_server_state" = "已連線"; +"disconnected_server_state" = "已中斷連線"; +"tray_open_window" = "開啟"; +"quit" = "退出"; diff --git a/src/cordova/import_messages.action.mjs b/src/cordova/import_messages.action.mjs index 7fa226afcbe..cf1daf796a6 100644 --- a/src/cordova/import_messages.action.mjs +++ b/src/cordova/import_messages.action.mjs @@ -13,6 +13,7 @@ // limitations under the License. import chalk from 'chalk'; +import minimist from 'minimist'; import path from 'path'; import rmfr from 'rmfr'; import url from 'url'; @@ -20,12 +21,22 @@ import {getRootDir} from '../build/get_root_dir.mjs'; import {readFile, readdir, writeFile, mkdir} from 'fs/promises'; import {getNativeLocale as getNativeAndroidLocale} from './android/get_native_locale.mjs'; import XML from 'xmlbuilder2'; +import I18N from 'i18n-strings-files'; + +const ANDROID = 'android'; +const IOS = 'ios'; +const VALID_PLATFORMS = [ANDROID, IOS]; + +const SOURCE_MESSAGES_DIR = 'www/messages'; const ANDROID_STRINGS_DIR = 'src/cordova/plugin/android/resources/strings/'; const ANDROID_STRINGS_FILENAME = 'strings.xml'; const ANDROID_XML_STRING_ID_PROPERTY = '@name'; const ANDROID_XML_TEXT_CONTENT = '#'; +const IOS_STRINGS_DIR = 'src/cordova/apple/xcode/ios/Outline/Resources/'; +const IOS_STRINGS_FILENAME = 'Localizable.strings'; + function escapeXmlCharacters(str) { return str .replace(/"/g, '\\"') @@ -35,9 +46,30 @@ function escapeXmlCharacters(str) { .replace(/&/g, '\\&'); } -export async function main() { +/** + * Verifies and returns the specified platform. + * @param {string[]} parameters The list of action arguments passed in + * @returns {Object} Object containing the specificed platform. + */ +function getActionParameters(cliArguments) { + console.log(minimist(cliArguments)); + const { + _: [platform = ''], + } = minimist(cliArguments); + + if (!VALID_PLATFORMS.includes(platform)) { + throw new TypeError( + `Platform "${platform}" is not a valid target for importing messages. ` + + `Must be one of "${VALID_PLATFORMS.join('", "')}"` + ); + } + + return {platform}; +} + +async function importAndroidMessages() { const outputDir = path.join(getRootDir(), ANDROID_STRINGS_DIR); - const requiredAndroidStrings = XML.create( + const requiredStrings = XML.create( await readFile(path.join(outputDir, 'values', ANDROID_STRINGS_FILENAME), 'utf8') ).end({format: 'object'}).resources.string; @@ -45,9 +77,7 @@ export async function main() { // cleared. await rmfr(path.join(outputDir, 'values-*'), {glob: true}); - console.group(chalk.white(`▶ importing Android messages:`)); - - const messagesDir = path.join(getRootDir(), 'www/messages'); + const messagesDir = path.join(getRootDir(), SOURCE_MESSAGES_DIR); for (const messagesFilename of await readdir(messagesDir)) { const polymerLang = path.basename(messagesFilename, path.extname(messagesFilename)); console.log(chalk.gray(`Importing \`${polymerLang}\``)); @@ -58,28 +88,84 @@ export async function main() { const messagesFilepath = path.join(messagesDir, messagesFilename); const messageData = JSON.parse(await readFile(messagesFilepath, 'utf8')); - const androidStrings = []; - for (const requiredString of requiredAndroidStrings) { + const outputStrings = []; + for (const requiredString of requiredStrings) { const messageId = requiredString[ANDROID_XML_STRING_ID_PROPERTY].replaceAll('_', '-'); const fallbackContent = requiredString[ANDROID_XML_TEXT_CONTENT]; - androidStrings.push({ + outputStrings.push({ [ANDROID_XML_STRING_ID_PROPERTY]: requiredString[ANDROID_XML_STRING_ID_PROPERTY], [ANDROID_XML_TEXT_CONTENT]: escapeXmlCharacters(messageData[messageId] ?? fallbackContent), }); } const outputPath = path.join(localeDir, ANDROID_STRINGS_FILENAME); - console.log(chalk.gray(`Writing ${androidStrings.length} messages to ` + `\`${outputPath}\``)); + console.log(chalk.gray(`Writing ${outputStrings.length} messages to \`${outputPath}\``)); await mkdir(localeDir, {recursive: true}); await writeFile( outputPath, - XML.create({encoding: 'UTF-8'}, {resources: {string: androidStrings}}).end({prettyPrint: true, wellFormed: true}) + XML.create({encoding: 'UTF-8'}, {resources: {string: outputStrings}}).end({prettyPrint: true, wellFormed: true}) ); } +} + +async function importIosMessages() { + const outputDir = path.join(getRootDir(), IOS_STRINGS_DIR); + const requiredStrings = I18N.readFileSync(path.join(outputDir, 'en.lproj', IOS_STRINGS_FILENAME), { + encoding: 'UTF-8', + }); + + // Clear all existing locales first, so languages we stop supporting get + // cleared. + await rmfr(path.join(outputDir, '*.lproj')); + + const messagesDir = path.join(getRootDir(), SOURCE_MESSAGES_DIR); + for (const messagesFilename of await readdir(messagesDir)) { + const polymerLang = path.basename(messagesFilename, path.extname(messagesFilename)); + console.log(chalk.gray(`Importing \`${polymerLang}\``)); + + const iosLocale = polymerLang; + const localeDir = path.join(outputDir, `${iosLocale}.lproj`); + + const messagesFilepath = path.join(messagesDir, messagesFilename); + const messageData = JSON.parse(await readFile(messagesFilepath, 'utf8')); + + const outputStrings = {}; + for (const [key, value] of Object.entries(requiredStrings)) { + const messageId = key.replaceAll('_', '-'); + const fallbackContent = value; + + outputStrings[key] = messageData[messageId] ?? fallbackContent; + } + const outputPath = path.join(localeDir, IOS_STRINGS_FILENAME); + console.log(chalk.gray(`Writing ${Object.values(outputStrings).length} messages to \`${outputPath}\``)); + await mkdir(localeDir, {recursive: true}); + I18N.writeFileSync(outputPath, outputStrings, {encoding: 'UTF-8'}); + } +} + +/** + * Imports message translations for the specified Cordova project. + * @param {string[]} parameters The list of action arguments passed in. + */ +async function main(...parameters) { + const {platform} = getActionParameters(parameters); + console.group(chalk.white(`▶ importing ${platform} messages:`)); + + switch (platform) { + case ANDROID: + await importAndroidMessages(); + break; + case IOS: + await importIosMessages(); + break; + default: + throw new Error(`Message import not implemented for platform "${platform}"`); + } + console.groupEnd(); } if (import.meta.url === url.pathToFileURL(process.argv[1]).href) { - await main(); + await main(...process.argv.slice(2)); } From d972fbe0b151c035c3f78814273672c7c3d8700c Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Mon, 24 Jul 2023 18:29:20 -0400 Subject: [PATCH 02/15] Move message loading into a function to be shared across Android and iOS. --- src/cordova/import_messages.action.mjs | 50 +++++++++++++++----------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/src/cordova/import_messages.action.mjs b/src/cordova/import_messages.action.mjs index cf1daf796a6..a2e9ac1000d 100644 --- a/src/cordova/import_messages.action.mjs +++ b/src/cordova/import_messages.action.mjs @@ -67,6 +67,25 @@ function getActionParameters(cliArguments) { return {platform}; } +/** + * Retrieves the source messages in all available translations. + * @returns {Map} A map of locale->messages. + */ +async function loadMessages() { + const messages = new Map(); + + const messagesDir = path.join(getRootDir(), SOURCE_MESSAGES_DIR); + for (const messagesFilename of await readdir(messagesDir)) { + const lang = path.basename(messagesFilename, path.extname(messagesFilename)); + const messagesFilepath = path.join(messagesDir, messagesFilename); + const messageData = JSON.parse(await readFile(messagesFilepath, 'utf8')); + messages.set(lang, messageData); + } + + return messages; +} + +/** Imports and writes messages for Android. */ async function importAndroidMessages() { const outputDir = path.join(getRootDir(), ANDROID_STRINGS_DIR); const requiredStrings = XML.create( @@ -77,16 +96,9 @@ async function importAndroidMessages() { // cleared. await rmfr(path.join(outputDir, 'values-*'), {glob: true}); - const messagesDir = path.join(getRootDir(), SOURCE_MESSAGES_DIR); - for (const messagesFilename of await readdir(messagesDir)) { - const polymerLang = path.basename(messagesFilename, path.extname(messagesFilename)); - console.log(chalk.gray(`Importing \`${polymerLang}\``)); - - const androidLocale = getNativeAndroidLocale(polymerLang); - const localeDir = path.join(outputDir, `values-${androidLocale}`); - - const messagesFilepath = path.join(messagesDir, messagesFilename); - const messageData = JSON.parse(await readFile(messagesFilepath, 'utf8')); + for (const [lang, messageData] of await loadMessages()) { + console.log(chalk.gray(`Importing \`${lang}\``)); + const androidLocale = getNativeAndroidLocale(lang); const outputStrings = []; for (const requiredString of requiredStrings) { @@ -99,6 +111,7 @@ async function importAndroidMessages() { }); } + const localeDir = path.join(outputDir, `values-${androidLocale}`); const outputPath = path.join(localeDir, ANDROID_STRINGS_FILENAME); console.log(chalk.gray(`Writing ${outputStrings.length} messages to \`${outputPath}\``)); await mkdir(localeDir, {recursive: true}); @@ -109,6 +122,7 @@ async function importAndroidMessages() { } } +/** Imports and writes messages for iOS. */ async function importIosMessages() { const outputDir = path.join(getRootDir(), IOS_STRINGS_DIR); const requiredStrings = I18N.readFileSync(path.join(outputDir, 'en.lproj', IOS_STRINGS_FILENAME), { @@ -117,18 +131,10 @@ async function importIosMessages() { // Clear all existing locales first, so languages we stop supporting get // cleared. - await rmfr(path.join(outputDir, '*.lproj')); + await rmfr(path.join(outputDir, '*.lproj'), {glob: true}); - const messagesDir = path.join(getRootDir(), SOURCE_MESSAGES_DIR); - for (const messagesFilename of await readdir(messagesDir)) { - const polymerLang = path.basename(messagesFilename, path.extname(messagesFilename)); - console.log(chalk.gray(`Importing \`${polymerLang}\``)); - - const iosLocale = polymerLang; - const localeDir = path.join(outputDir, `${iosLocale}.lproj`); - - const messagesFilepath = path.join(messagesDir, messagesFilename); - const messageData = JSON.parse(await readFile(messagesFilepath, 'utf8')); + for (const [lang, messageData] of await loadMessages()) { + console.log(chalk.gray(`Importing \`${lang}\``)); const outputStrings = {}; for (const [key, value] of Object.entries(requiredStrings)) { @@ -137,6 +143,8 @@ async function importIosMessages() { outputStrings[key] = messageData[messageId] ?? fallbackContent; } + + const localeDir = path.join(outputDir, `${lang}.lproj`); const outputPath = path.join(localeDir, IOS_STRINGS_FILENAME); console.log(chalk.gray(`Writing ${Object.values(outputStrings).length} messages to \`${outputPath}\``)); await mkdir(localeDir, {recursive: true}); From d2ffe7a5893e7c70835b7f3b79e72b817fa80f71 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Fri, 28 Jul 2023 19:04:29 -0400 Subject: [PATCH 03/15] Refactor `import_messages` to reduce duplication. --- src/cordova/android/get_native_locale.mjs | 24 ----- src/cordova/android/import_messages.mjs | 84 ++++++++++++++++ src/cordova/apple/import_messages.mjs | 46 +++++++++ src/cordova/import_messages.action.mjs | 111 ++++++---------------- 4 files changed, 157 insertions(+), 108 deletions(-) delete mode 100644 src/cordova/android/get_native_locale.mjs create mode 100644 src/cordova/android/import_messages.mjs create mode 100644 src/cordova/apple/import_messages.mjs diff --git a/src/cordova/android/get_native_locale.mjs b/src/cordova/android/get_native_locale.mjs deleted file mode 100644 index 07bf1231aa2..00000000000 --- a/src/cordova/android/get_native_locale.mjs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2023 The Outline Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -export const getNativeLocale = polymerLang => { - switch (polymerLang) { - case 'es-419': - return 'es'; - case 'sr-Latn': - return 'b+sr+Latn'; - default: - return polymerLang.replace('-', '-r'); - } -}; diff --git a/src/cordova/android/import_messages.mjs b/src/cordova/android/import_messages.mjs new file mode 100644 index 00000000000..e9f3079cf29 --- /dev/null +++ b/src/cordova/android/import_messages.mjs @@ -0,0 +1,84 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import {readFile, writeFile} from 'fs/promises'; +import path from 'path'; +import XML from 'xmlbuilder2'; + +const STRINGS_DIR = 'src/cordova/plugin/android/resources/strings/'; +const STRINGS_FILENAME = 'strings.xml'; +const XML_STRING_ID_PROPERTY = '@name'; +const XML_TEXT_CONTENT = '#'; + +function escapeXmlCharacters(str) { + return str + .replace(/"/g, '\\"') + .replace(/'/g, "\\'") + .replace(//g, '\\>;') + .replace(/&/g, '\\&'); +} + +function getNativeLocale(polymerLang) { + switch (polymerLang) { + case 'es-419': + return 'es'; + case 'sr-Latn': + return 'b+sr+Latn'; + default: + return polymerLang.replace('-', '-r'); + } +} + +/** + * Retrieves a filepath for a given locale to read/write strings to. + * @param {string} locale A locale for which to get a strings filepath. + * @returns {string} The filepath. + */ +export function getStringsFilepath(polymerLang) { + const localeSuffix = polymerLang ? `-${getNativeLocale(polymerLang)}` : ''; + return path.join(STRINGS_DIR, `values${localeSuffix}`, STRINGS_FILENAME); +} + +/** + * Reads messages that require translations. + * @return {Map} messages The messages to translate. + */ +export async function readMessages() { + const strings = await XML.create(await readFile(getStringsFilepath(), 'utf8')).end({format: 'object'}).resources + .string; + return strings.reduce((acc, string) => { + return acc.set(string[XML_STRING_ID_PROPERTY], string[XML_TEXT_CONTENT]); + }, new Map()); +} + +/** + * Writes output messages to a given path in the Android expected format. + * @param {string} path The path to write the messages to. + * @param {Map} messages The messages to write. + */ +export async function writeMessages(path, messages) { + const output = Object.entries(messages).reduce((acc, [key, value]) => { + acc.push({ + [XML_STRING_ID_PROPERTY]: key, + [XML_TEXT_CONTENT]: escapeXmlCharacters(value), + }); + return acc; + }, []); + + await writeFile( + path, + XML.create({encoding: 'UTF-8'}, {resources: {string: output}}).end({prettyPrint: true, wellFormed: true}) + ); +} diff --git a/src/cordova/apple/import_messages.mjs b/src/cordova/apple/import_messages.mjs new file mode 100644 index 00000000000..8ae833e9a3a --- /dev/null +++ b/src/cordova/apple/import_messages.mjs @@ -0,0 +1,46 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import path from 'path'; +import I18N from 'i18n-strings-files'; + +const STRINGS_DIR = 'src/cordova/apple/xcode/ios/Outline/Resources/'; +const STRINGS_FILENAME = 'Localizable.strings'; + +/** + * Retrieves a filepath for a given locale to read/write strings to. + * @param {string} locale A locale for which to get a strings filepath. + * @returns {string} The filepath. + */ +export function getStringsFilepath(locale) { + return path.join(STRINGS_DIR, `${locale}.lproj`, STRINGS_FILENAME); +} + +/** + * Reads messages that require translations. + * @return {Map} messages The messages to translate. + */ +export async function readMessages() { + const messages = I18N.readFileSync(getStringsFilepath('en'), {encoding: 'UTF-8'}); + return new Map(Object.entries(messages)); +} + +/** + * Writes output messages to a given path in the Apple expected format. + * @param {string} path The path to write the messages to. + * @param {Map} messages The messages to write. + */ +export async function writeMessages(path, messages) { + I18N.writeFileSync(path, messages, {encoding: 'UTF-8'}); +} diff --git a/src/cordova/import_messages.action.mjs b/src/cordova/import_messages.action.mjs index a2e9ac1000d..ff1cb8a09e4 100644 --- a/src/cordova/import_messages.action.mjs +++ b/src/cordova/import_messages.action.mjs @@ -15,13 +15,11 @@ import chalk from 'chalk'; import minimist from 'minimist'; import path from 'path'; -import rmfr from 'rmfr'; import url from 'url'; import {getRootDir} from '../build/get_root_dir.mjs'; -import {readFile, readdir, writeFile, mkdir} from 'fs/promises'; -import {getNativeLocale as getNativeAndroidLocale} from './android/get_native_locale.mjs'; -import XML from 'xmlbuilder2'; -import I18N from 'i18n-strings-files'; +import {readFile, readdir, mkdir} from 'fs/promises'; +import * as ANDROID_IMPORTER from './android/import_messages.mjs'; +import * as IOS_IMPORTER from './apple/import_messages.mjs'; const ANDROID = 'android'; const IOS = 'ios'; @@ -29,30 +27,12 @@ const VALID_PLATFORMS = [ANDROID, IOS]; const SOURCE_MESSAGES_DIR = 'www/messages'; -const ANDROID_STRINGS_DIR = 'src/cordova/plugin/android/resources/strings/'; -const ANDROID_STRINGS_FILENAME = 'strings.xml'; -const ANDROID_XML_STRING_ID_PROPERTY = '@name'; -const ANDROID_XML_TEXT_CONTENT = '#'; - -const IOS_STRINGS_DIR = 'src/cordova/apple/xcode/ios/Outline/Resources/'; -const IOS_STRINGS_FILENAME = 'Localizable.strings'; - -function escapeXmlCharacters(str) { - return str - .replace(/"/g, '\\"') - .replace(/'/g, "\\'") - .replace(//g, '\\>;') - .replace(/&/g, '\\&'); -} - /** * Verifies and returns the specified platform. * @param {string[]} parameters The list of action arguments passed in * @returns {Object} Object containing the specificed platform. */ function getActionParameters(cliArguments) { - console.log(minimist(cliArguments)); const { _: [platform = ''], } = minimist(cliArguments); @@ -85,70 +65,29 @@ async function loadMessages() { return messages; } -/** Imports and writes messages for Android. */ -async function importAndroidMessages() { - const outputDir = path.join(getRootDir(), ANDROID_STRINGS_DIR); - const requiredStrings = XML.create( - await readFile(path.join(outputDir, 'values', ANDROID_STRINGS_FILENAME), 'utf8') - ).end({format: 'object'}).resources.string; - - // Clear all existing locales first, so languages we stop supporting get - // cleared. - await rmfr(path.join(outputDir, 'values-*'), {glob: true}); - - for (const [lang, messageData] of await loadMessages()) { - console.log(chalk.gray(`Importing \`${lang}\``)); - const androidLocale = getNativeAndroidLocale(lang); - - const outputStrings = []; - for (const requiredString of requiredStrings) { - const messageId = requiredString[ANDROID_XML_STRING_ID_PROPERTY].replaceAll('_', '-'); - const fallbackContent = requiredString[ANDROID_XML_TEXT_CONTENT]; - - outputStrings.push({ - [ANDROID_XML_STRING_ID_PROPERTY]: requiredString[ANDROID_XML_STRING_ID_PROPERTY], - [ANDROID_XML_TEXT_CONTENT]: escapeXmlCharacters(messageData[messageId] ?? fallbackContent), - }); - } - - const localeDir = path.join(outputDir, `values-${androidLocale}`); - const outputPath = path.join(localeDir, ANDROID_STRINGS_FILENAME); - console.log(chalk.gray(`Writing ${outputStrings.length} messages to \`${outputPath}\``)); - await mkdir(localeDir, {recursive: true}); - await writeFile( - outputPath, - XML.create({encoding: 'UTF-8'}, {resources: {string: outputStrings}}).end({prettyPrint: true, wellFormed: true}) - ); - } -} - -/** Imports and writes messages for iOS. */ -async function importIosMessages() { - const outputDir = path.join(getRootDir(), IOS_STRINGS_DIR); - const requiredStrings = I18N.readFileSync(path.join(outputDir, 'en.lproj', IOS_STRINGS_FILENAME), { - encoding: 'UTF-8', - }); - - // Clear all existing locales first, so languages we stop supporting get - // cleared. - await rmfr(path.join(outputDir, '*.lproj'), {glob: true}); +/** + * Imports message translations. + * @param {Function} getStringsFilepath A function to get a filepath to + * read/write strings for a given locale. + * @param {Function} readMessages A function to read required messages. + * @param {Function} writeMessages A function to write the output messages. + */ +async function importMessages(getStringsFilepath, readMessages, writeMessages) { + const requiredMessages = await readMessages(); - for (const [lang, messageData] of await loadMessages()) { - console.log(chalk.gray(`Importing \`${lang}\``)); + for (const [locale, messageData] of await loadMessages()) { + console.log(chalk.gray(`Importing \`${locale}\``)); - const outputStrings = {}; - for (const [key, value] of Object.entries(requiredStrings)) { + const outputMessages = {}; + for (const [key, value] of requiredMessages.entries()) { const messageId = key.replaceAll('_', '-'); - const fallbackContent = value; - - outputStrings[key] = messageData[messageId] ?? fallbackContent; + outputMessages[key] = messageData[messageId] ?? value; } - const localeDir = path.join(outputDir, `${lang}.lproj`); - const outputPath = path.join(localeDir, IOS_STRINGS_FILENAME); - console.log(chalk.gray(`Writing ${Object.values(outputStrings).length} messages to \`${outputPath}\``)); - await mkdir(localeDir, {recursive: true}); - I18N.writeFileSync(outputPath, outputStrings, {encoding: 'UTF-8'}); + const outputPath = getStringsFilepath(locale); + console.log(chalk.gray(`Writing ${Object.values(outputMessages).length} messages to \`${outputPath}\``)); + await mkdir(path.dirname(outputPath), {recursive: true}); + writeMessages(outputPath, outputMessages); } } @@ -162,10 +101,14 @@ async function main(...parameters) { switch (platform) { case ANDROID: - await importAndroidMessages(); + await importMessages( + ANDROID_IMPORTER.getStringsFilepath, + ANDROID_IMPORTER.readMessages, + ANDROID_IMPORTER.writeMessages + ); break; case IOS: - await importIosMessages(); + await importMessages(IOS_IMPORTER.getStringsFilepath, IOS_IMPORTER.readMessages, IOS_IMPORTER.writeMessages); break; default: throw new Error(`Message import not implemented for platform "${platform}"`); From 2fbddf51464197accfb80bd9fee621b099855758 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Fri, 28 Jul 2023 19:09:49 -0400 Subject: [PATCH 04/15] Update function types in JSDoc annotations. --- src/cordova/import_messages.action.mjs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cordova/import_messages.action.mjs b/src/cordova/import_messages.action.mjs index ff1cb8a09e4..b9681795a9e 100644 --- a/src/cordova/import_messages.action.mjs +++ b/src/cordova/import_messages.action.mjs @@ -67,10 +67,12 @@ async function loadMessages() { /** * Imports message translations. - * @param {Function} getStringsFilepath A function to get a filepath to - * read/write strings for a given locale. - * @param {Function} readMessages A function to read required messages. - * @param {Function} writeMessages A function to write the output messages. + * @param {function(string): string} getStringsFilepath A function to get a + * filepath to read/write strings for a given locale. + * @param {function(): Map} readMessages A function to read + * required messages. + * @param {function(string, Map)} writeMessages A function to + * write the output messages. */ async function importMessages(getStringsFilepath, readMessages, writeMessages) { const requiredMessages = await readMessages(); From a6267e470444bcfc1672137ff93b1eeeb008c565 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Fri, 28 Jul 2023 19:19:08 -0400 Subject: [PATCH 05/15] Fix typo. --- src/cordova/import_messages.action.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cordova/import_messages.action.mjs b/src/cordova/import_messages.action.mjs index b9681795a9e..da3f6899fa9 100644 --- a/src/cordova/import_messages.action.mjs +++ b/src/cordova/import_messages.action.mjs @@ -28,9 +28,9 @@ const VALID_PLATFORMS = [ANDROID, IOS]; const SOURCE_MESSAGES_DIR = 'www/messages'; /** - * Verifies and returns the specified platform. - * @param {string[]} parameters The list of action arguments passed in - * @returns {Object} Object containing the specificed platform. + * Parses and verifies the action parameters and returns the specified platform. + * @param {string[]} parameters The list of action arguments passed in. + * @returns {Object} Object containing the specified platform. */ function getActionParameters(cliArguments) { const { From 5265666bef6b60db4118b9d788c8f97de63a60ee Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Tue, 8 Aug 2023 00:03:29 -0400 Subject: [PATCH 06/15] Change strings directory into a list of strings. --- src/cordova/android/import_messages.mjs | 4 ++-- src/cordova/apple/import_messages.mjs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cordova/android/import_messages.mjs b/src/cordova/android/import_messages.mjs index e9f3079cf29..f85f5596f67 100644 --- a/src/cordova/android/import_messages.mjs +++ b/src/cordova/android/import_messages.mjs @@ -16,7 +16,7 @@ import {readFile, writeFile} from 'fs/promises'; import path from 'path'; import XML from 'xmlbuilder2'; -const STRINGS_DIR = 'src/cordova/plugin/android/resources/strings/'; +const STRINGS_DIR = ['src', 'cordova', 'plugin', 'android', 'resources', 'strings']; const STRINGS_FILENAME = 'strings.xml'; const XML_STRING_ID_PROPERTY = '@name'; const XML_TEXT_CONTENT = '#'; @@ -48,7 +48,7 @@ function getNativeLocale(polymerLang) { */ export function getStringsFilepath(polymerLang) { const localeSuffix = polymerLang ? `-${getNativeLocale(polymerLang)}` : ''; - return path.join(STRINGS_DIR, `values${localeSuffix}`, STRINGS_FILENAME); + return path.join(...STRINGS_DIR, `values${localeSuffix}`, STRINGS_FILENAME); } /** diff --git a/src/cordova/apple/import_messages.mjs b/src/cordova/apple/import_messages.mjs index 8ae833e9a3a..a858aa35d3c 100644 --- a/src/cordova/apple/import_messages.mjs +++ b/src/cordova/apple/import_messages.mjs @@ -15,7 +15,7 @@ import path from 'path'; import I18N from 'i18n-strings-files'; -const STRINGS_DIR = 'src/cordova/apple/xcode/ios/Outline/Resources/'; +const STRINGS_DIR = ['src', 'cordova', 'apple', 'xcode', 'ios', 'Outline', 'Resources']; const STRINGS_FILENAME = 'Localizable.strings'; /** @@ -24,7 +24,7 @@ const STRINGS_FILENAME = 'Localizable.strings'; * @returns {string} The filepath. */ export function getStringsFilepath(locale) { - return path.join(STRINGS_DIR, `${locale}.lproj`, STRINGS_FILENAME); + return path.join(...STRINGS_DIR, `${locale}.lproj`, STRINGS_FILENAME); } /** From fbb52c575306af4d482cfb777ef0b864363a36b7 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Mon, 14 Aug 2023 22:09:04 -0400 Subject: [PATCH 07/15] Update the npm-bundled version of node-gyp. --- .github/workflows/build_and_test_debug.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build_and_test_debug.yml b/.github/workflows/build_and_test_debug.yml index e028a99bd41..90f50238270 100644 --- a/.github/workflows/build_and_test_debug.yml +++ b/.github/workflows/build_and_test_debug.yml @@ -108,6 +108,11 @@ jobs: node-version: 18 cache: npm + - name: Update the npm-bundled version of node-gyp + run: | # https://github.com/nodejs/node-gyp/blob/main/docs/Updating-npm-bundled-node-gyp.md + npm -v + npm explore npm/node_modules/@npmcli/run-script -g -- npm_config_global=false npm install node-gyp@latest + - name: Install NPM Dependencies run: npm ci From e52a7a8b42a042ddf3cba9ba0fce91bfc31eb697 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Mon, 14 Aug 2023 22:28:50 -0400 Subject: [PATCH 08/15] Force npm to use global installed node-gyp. --- .github/workflows/build_and_test_debug.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_and_test_debug.yml b/.github/workflows/build_and_test_debug.yml index 90f50238270..b1520800a6b 100644 --- a/.github/workflows/build_and_test_debug.yml +++ b/.github/workflows/build_and_test_debug.yml @@ -108,10 +108,10 @@ jobs: node-version: 18 cache: npm - - name: Update the npm-bundled version of node-gyp - run: | # https://github.com/nodejs/node-gyp/blob/main/docs/Updating-npm-bundled-node-gyp.md - npm -v - npm explore npm/node_modules/@npmcli/run-script -g -- npm_config_global=false npm install node-gyp@latest + - name: Force npm to use global installed node-gyp + run: | # https://github.com/nodejs/node-gyp/blob/main/docs/Force-npm-to-use-global-node-gyp.md + npm install --global node-gyp@latest + npm config set node_gyp $(npm prefix -g)/lib/node_modules/node-gyp/bin/node-gyp.js - name: Install NPM Dependencies run: npm ci From e96efd035c42de8130fbb7d011be3d9d98402e87 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Thu, 17 Aug 2023 11:35:41 -0400 Subject: [PATCH 09/15] feat(cordova/apple/ios): add mac catalyst support (#1630) * Replace the `copy-www-build-step` script with build phases. * Add Mac Catalyst as a destination. * Update README to load xcworkspace from `./src/cordova/apple/` instead of `./platforms/ios/`. * Set separate bundle identifier for the Mac app built with Mac Catalyst. * Add `Package.resolved` back. It was likely accidentally removed in #1536. * Update local storage source directory for UIWebView->WKWebView migration for catalyst. * Pin `cordova-ios` dep to fix for splashscreen aspect ratio. * Rename `Images.xcassets` to `Assets.xcassets`. * Add the status bar button images. * Use `LSUIElement` to indicate this is a background app and shouldn't appear in the Dock. * Add an AppKit bridge and use it to create a status bar menu in catalyst. * Re-open the application window when use selects "Open" command from the status menu. * Stop any VPN connections on app termination. * Use `clang-format` to format Objective-C files. * Use `SwiftFormat` to format Swift files. * Set separate bundle identifier for the Mac Catalyst app built for release. Previously set it on the `Debug` build, but need to also set it on `Release` build. * Configure the app window to be a specific size. * Enable the embedded app launcher as a login item. * Use the macos app group in `PacketTunnelProvider` when on Catalyst. * Add some logs to the `OutlineStatusItemController` for easier debugging. * Do not try and add a `StatusItemController` automatically on AppKitBridge loads. We'll need to re-use this bridge in the upcoming launcher, which should not add its own menu item to the status bar. * Ignore locally loaded XCFramework bundles. * Add launcher to Catalyst. We set the launcher as a login item in Catalyst, and open the app if there Outline was connected at shutdown. * Run `clang-format` over `.m` files. * Ensure Sentry logs the right app group on Catalyst. * Run macos code on Catalyst in a few more places. * Do not run some code for `macOS` on `Catalyst`. * Add prefix to log message for consistency. * Use the `NETunnelProviderManager` to determine whether Outline was connected and the launcher should launch the application. * Automatic project data changes made by Xcode. * Set miminum macos deployment target to 10.15. * Set bundle ID for launcher to `launcher3`. * Move `AppDelegate` logic to category extension instead of overwriting the `AppDelegate` file auto-generated by Cordova. * Move Catalyst specific `AppDelegate` code to Swift. * Use `SwiftFormat` to format Swift files. * Replace `NSLog` with `DDLog`. * Use `SwiftFormat` to format Swift files. * Fix notifications for macos bundle and undo formatting to make the diff smaller. * Remove local `Tun2socks.xcframework` which got accidentally committed. * Undo README changes as they have already been updated in a previous PR. * Move catalyst code into `OutlineAppleLib`. * Remove reference to `OutlineLauncher`'s plist. * Fix some bad merges. * Remove an unnecessary `#if` guard. * Add a TODO to i18n the menu strings, which will happen in a fast-follow. * Review changes. * More changes for review. * Mark static function as public. * More changes. * Use enum instead of boolean to represent connection status. * Clean up some entitlement changes that aren't actually needed. * Undo some entitlement changes that were needed to create outgoing connections on macos. * Remove a single unneeded entitlement. * Only compile `OutlineCatalystApp` on Catalyst. * Fix ios build. * Add some method docs and change methods to standalone functions where no state is needed. * Remove unneeded `Sources` sections. * Revert "Remove unneeded `Sources` sections." This reverts commit 863ac93669498f376548b9cb83a8f703aeaadc3d. * Remove unneeded build phases. * Remove seemingly unneeded info list items. * Add the "compile sources" build phase back to the `AppKitBridge` bundle. * Fix macos build. * Move `OutlineCatalystApp` target into `OutlineAppleLib` product. * Rely on `NSNotification` extension from `OutlineAppleLib`. * Remove `Tun2socks` and `OutlineTunnel` dependency from launcher and add "compile sources" buildphase back in. * Select "Optimize interface for Mac" at the project level for Mac Catalyst. * Move much of the OutlinePlugin into a Swift package, leaving only Cordova-specific code in the plugin, renamed as `CDVOutline`. * Move status menu assets into Swift package. * No need to explicitly state resources for the Assets catalog as Xcode treats these as resources automatically. * Update the macos client to use the renamed `CDVOutline` plugin. * Revert `OutlinePlugin` changes and instead use a `NSNotification` target. * `OutlineNotifications` to `OutlineNotification`. * Add some TODOs. * Remove unnecessary parameter. --- package-lock.json | 293 +++++++++- package.json | 2 +- src/cordova/apple/OutlineAppleLib/.gitignore | 1 + .../apple/OutlineAppleLib/Package.swift | 51 +- src/cordova/apple/OutlineAppleLib/README.md | 5 +- .../OutlineAppKitBridge/AppKitBridge.swift | 83 +++ .../AppKitBridgeProtocol.swift | 28 + .../ConnectionStatus.swift | 19 + .../Resources/Assets.xcassets/Contents.json | 6 + .../Contents.json | 21 + .../outline-black-off-2x.png | Bin 0 -> 578 bytes .../Contents.json | 21 + .../outline-black-on-2x.png | Bin 0 -> 563 bytes .../StatusItemController.swift | 101 ++++ .../AppKitBundleLoader.swift | 37 ++ .../OutlineCatalystApp.swift | 61 +++ .../Sources/OutlineLauncher/AppDelegate.swift | 64 +++ .../NSNotification+Outline.swift | 30 ++ .../PacketTunnelProvider.m | 6 +- .../ios/Outline.xcodeproj/project.pbxproj | 509 ++++++++++++++++-- .../ios/Outline/Classes/AppDelegate+Outline.h | 24 + .../ios/Outline/Classes/AppDelegate+Outline.m | 41 ++ .../xcode/ios/Outline/Outline-Info.plist | 2 + .../xcode/ios/Outline/Outline.entitlements | 4 + .../ios/Outline/VpnExtension.entitlements | 6 + .../OutlineLauncher.entitlements | 18 + .../xcode/macos/Outline/Classes/AppDelegate.m | 7 +- .../plugin/apple/src/OutlinePlugin.swift | 274 +++++----- 28 files changed, 1478 insertions(+), 236 deletions(-) create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/AppKitBridge.swift create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/AppKitBridgeProtocol.swift create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/ConnectionStatus.swift create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/Contents.json create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/status_bar_button_image.imageset/Contents.json create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/status_bar_button_image.imageset/outline-black-off-2x.png create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/status_bar_button_image_connected.imageset/Contents.json create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/status_bar_button_image_connected.imageset/outline-black-on-2x.png create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineCatalystApp/AppKitBundleLoader.swift create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineCatalystApp/OutlineCatalystApp.swift create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineLauncher/AppDelegate.swift create mode 100644 src/cordova/apple/OutlineAppleLib/Sources/OutlineNotification/NSNotification+Outline.swift create mode 100644 src/cordova/apple/xcode/ios/Outline/Classes/AppDelegate+Outline.h create mode 100644 src/cordova/apple/xcode/ios/Outline/Classes/AppDelegate+Outline.m create mode 100644 src/cordova/apple/xcode/ios/OutlineLauncher/OutlineLauncher.entitlements diff --git a/package-lock.json b/package-lock.json index 5c79d23ad91..4af36f51a68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -74,7 +74,7 @@ "copy-webpack-plugin": "^5.1.1", "cordova-android": "^11.0.0", "cordova-browser": "~6.0.0", - "cordova-ios": "~6.3.0", + "cordova-ios": "github:apache/cordova-ios#1a5cd45e2243b239b5045a0ade9d2da1d779b72a", "cordova-lib": "^11.0.0", "cordova-osx": "github:apache/cordova-osx", "cordova-plugin-clipboard": "github:Jigsaw-Code/outline-cordova-plugin-clipboard#v2.0.0", @@ -7728,30 +7728,122 @@ } }, "node_modules/cordova-ios": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/cordova-ios/-/cordova-ios-6.3.0.tgz", - "integrity": "sha512-BZybgFzc7D0HmhkTYurFrRXiWgvYohmT7bwQsLPhf+VdiDjwGXbiSWgg3uP9MChvacCNcGXXUl2NhOaNC9UVaA==", + "version": "7.0.0-dev", + "resolved": "git+ssh://git@github.com/apache/cordova-ios.git#1a5cd45e2243b239b5045a0ade9d2da1d779b72a", + "integrity": "sha512-WKEu8ahzeLMby1ir8cb49dJKM4mgI1kXzGWjMldP0aILoRaPU/NENoxhJI5AQ6ozdXX4L3mD1+WkvncxLUNycw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "cordova-common": "^4.0.2", - "fs-extra": "^9.1.0", + "cordova-common": "^5.0.0", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", "ios-sim": "^8.0.2", - "nopt": "^5.0.0", - "plist": "^3.0.1", - "semver": "^7.3.4", + "nopt": "^7.1.0", + "plist": "^3.0.6", + "semver": "^7.4.0", "unorm": "^1.6.0", - "which": "^2.0.2", + "which": "^3.0.0", "xcode": "^3.0.1", "xml-escape": "^1.1.0" }, "engines": { - "node": ">=10" + "node": ">=16.13.0" + } + }, + "node_modules/cordova-ios/node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/cordova-ios/node_modules/bplist-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", + "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "dev": true, + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/cordova-ios/node_modules/cordova-common": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cordova-common/-/cordova-common-5.0.0.tgz", + "integrity": "sha512-6Aa7o52/iEvsKx6K94ijzFel5acCULR49KL27OUVhEpJ4oS7Dc3y2eOP1Eu0P4Wmiw/eLEDQjGXGiAa2D5zFZA==", + "dev": true, + "dependencies": { + "@netflix/nerror": "^1.1.3", + "ansi": "^0.3.1", + "bplist-parser": "^0.3.2", + "cross-spawn": "^7.0.3", + "elementtree": "^0.1.7", + "endent": "^2.1.0", + "fast-glob": "^3.2.12", + "fs-extra": "^11.1.0", + "glob": "^7.1.6", + "lodash.assign": "^4.2.0", + "lodash.isdate": "^4.0.1", + "lodash.isobject": "^3.0.2", + "lodash.zip": "^4.2.0", + "plist": "^3.0.6", + "q": "^1.5.1", + "read-chunk": "^3.2.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/cordova-ios/node_modules/endent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", + "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", + "dev": true, + "dependencies": { + "dedent": "^0.7.0", + "fast-json-parse": "^1.0.3", + "objectorarray": "^1.0.5" + } + }, + "node_modules/cordova-ios/node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/cordova-ios/node_modules/nopt": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.1.0.tgz", + "integrity": "sha512-ZFPLe9Iu0tnx7oWhFxAo4s7QTn8+NNDDxYNaKLjE7Dp0tbakQ3M1QhQzsnzXHQBTUO3K9BmwaxnyO8Ayn2I95Q==", + "dev": true, + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/cordova-ios/node_modules/semver": { - "version": "7.3.7", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", "dev": true, - "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -7762,6 +7854,21 @@ "node": ">=10" } }, + "node_modules/cordova-ios/node_modules/which": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", + "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/cordova-lib": { "version": "11.0.0", "dev": true, @@ -10362,9 +10469,10 @@ "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.2.11", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -13959,6 +14067,12 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw==", + "dev": true + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "dev": true, @@ -13973,10 +14087,22 @@ "version": "4.1.2", "license": "MIT" }, + "node_modules/lodash.isdate": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isdate/-/lodash.isdate-4.0.1.tgz", + "integrity": "sha512-hg5B1GD+R9egsBgMwmAhk+V53Us03TVvXT4dnyKugEfsD4QKuG9Wlyvxq8OGy2nu7qVGsh4DRSnMk33hoWBq/Q==", + "dev": true + }, "node_modules/lodash.isequal": { "version": "4.5.0", "license": "MIT" }, + "node_modules/lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==", + "dev": true + }, "node_modules/lodash.memoize": { "version": "4.1.2", "dev": true, @@ -13992,6 +14118,12 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", + "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==", + "dev": true + }, "node_modules/log4js": { "version": "6.6.1", "dev": true, @@ -26502,29 +26634,112 @@ } }, "cordova-ios": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/cordova-ios/-/cordova-ios-6.3.0.tgz", - "integrity": "sha512-BZybgFzc7D0HmhkTYurFrRXiWgvYohmT7bwQsLPhf+VdiDjwGXbiSWgg3uP9MChvacCNcGXXUl2NhOaNC9UVaA==", + "version": "git+ssh://git@github.com/apache/cordova-ios.git#1a5cd45e2243b239b5045a0ade9d2da1d779b72a", + "integrity": "sha512-WKEu8ahzeLMby1ir8cb49dJKM4mgI1kXzGWjMldP0aILoRaPU/NENoxhJI5AQ6ozdXX4L3mD1+WkvncxLUNycw==", "dev": true, + "from": "cordova-ios@github:apache/cordova-ios#1a5cd45e2243b239b5045a0ade9d2da1d779b72a", "requires": { - "cordova-common": "^4.0.2", - "fs-extra": "^9.1.0", + "cordova-common": "^5.0.0", + "execa": "^5.1.1", + "fs-extra": "^11.1.1", "ios-sim": "^8.0.2", - "nopt": "^5.0.0", - "plist": "^3.0.1", - "semver": "^7.3.4", + "nopt": "^7.1.0", + "plist": "^3.0.6", + "semver": "^7.4.0", "unorm": "^1.6.0", - "which": "^2.0.2", + "which": "^3.0.0", "xcode": "^3.0.1", "xml-escape": "^1.1.0" }, "dependencies": { + "abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true + }, + "bplist-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", + "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "dev": true, + "requires": { + "big-integer": "1.6.x" + } + }, + "cordova-common": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cordova-common/-/cordova-common-5.0.0.tgz", + "integrity": "sha512-6Aa7o52/iEvsKx6K94ijzFel5acCULR49KL27OUVhEpJ4oS7Dc3y2eOP1Eu0P4Wmiw/eLEDQjGXGiAa2D5zFZA==", + "dev": true, + "requires": { + "@netflix/nerror": "^1.1.3", + "ansi": "^0.3.1", + "bplist-parser": "^0.3.2", + "cross-spawn": "^7.0.3", + "elementtree": "^0.1.7", + "endent": "^2.1.0", + "fast-glob": "^3.2.12", + "fs-extra": "^11.1.0", + "glob": "^7.1.6", + "lodash.assign": "^4.2.0", + "lodash.isdate": "^4.0.1", + "lodash.isobject": "^3.0.2", + "lodash.zip": "^4.2.0", + "plist": "^3.0.6", + "q": "^1.5.1", + "read-chunk": "^3.2.0", + "strip-bom": "^4.0.0" + } + }, + "endent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", + "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", + "dev": true, + "requires": { + "dedent": "^0.7.0", + "fast-json-parse": "^1.0.3", + "objectorarray": "^1.0.5" + } + }, + "fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "nopt": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.1.0.tgz", + "integrity": "sha512-ZFPLe9Iu0tnx7oWhFxAo4s7QTn8+NNDDxYNaKLjE7Dp0tbakQ3M1QhQzsnzXHQBTUO3K9BmwaxnyO8Ayn2I95Q==", + "dev": true, + "requires": { + "abbrev": "^2.0.0" + } + }, "semver": { - "version": "7.3.7", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", "dev": true, "requires": { "lru-cache": "^6.0.0" } + }, + "which": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", + "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -28290,7 +28505,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.11", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -30681,6 +30898,12 @@ "version": "4.17.21", "dev": true }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw==", + "dev": true + }, "lodash.camelcase": { "version": "4.3.0", "dev": true @@ -30692,9 +30915,21 @@ "lodash.escaperegexp": { "version": "4.1.2" }, + "lodash.isdate": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isdate/-/lodash.isdate-4.0.1.tgz", + "integrity": "sha512-hg5B1GD+R9egsBgMwmAhk+V53Us03TVvXT4dnyKugEfsD4QKuG9Wlyvxq8OGy2nu7qVGsh4DRSnMk33hoWBq/Q==", + "dev": true + }, "lodash.isequal": { "version": "4.5.0" }, + "lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==", + "dev": true + }, "lodash.memoize": { "version": "4.1.2", "dev": true @@ -30707,6 +30942,12 @@ "version": "4.5.0", "dev": true }, + "lodash.zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", + "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==", + "dev": true + }, "log4js": { "version": "6.6.1", "dev": true, diff --git a/package.json b/package.json index d191e750278..700a3586273 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "copy-webpack-plugin": "^5.1.1", "cordova-android": "^11.0.0", "cordova-browser": "~6.0.0", - "cordova-ios": "~6.3.0", + "cordova-ios": "github:apache/cordova-ios#1a5cd45e2243b239b5045a0ade9d2da1d779b72a", "cordova-lib": "^11.0.0", "cordova-osx": "github:apache/cordova-osx", "cordova-plugin-clipboard": "github:Jigsaw-Code/outline-cordova-plugin-clipboard#v2.0.0", diff --git a/src/cordova/apple/OutlineAppleLib/.gitignore b/src/cordova/apple/OutlineAppleLib/.gitignore index 5922fdaa563..c4604397f38 100644 --- a/src/cordova/apple/OutlineAppleLib/.gitignore +++ b/src/cordova/apple/OutlineAppleLib/.gitignore @@ -2,6 +2,7 @@ /.build /Packages /*.xcodeproj +/*.xcframework xcuserdata/ DerivedData/ .swiftpm/config/registries.json diff --git a/src/cordova/apple/OutlineAppleLib/Package.swift b/src/cordova/apple/OutlineAppleLib/Package.swift index 966634ddba4..0219c673d4b 100644 --- a/src/cordova/apple/OutlineAppleLib/Package.swift +++ b/src/cordova/apple/OutlineAppleLib/Package.swift @@ -8,39 +8,71 @@ let package = Package( products: [ .library( name: "OutlineAppleLib", - targets: ["Tun2socks", "OutlineSentryLogger", "OutlineTunnel"]), + targets: ["Tun2socks", "OutlineSentryLogger", "OutlineTunnel", "OutlineCatalystApp", "OutlineNotification"] + ), + .library( + name: "OutlineLauncher", + targets: ["OutlineLauncher"] + ), + .library( + name: "OutlineAppKitBridge", + targets: ["OutlineAppKitBridge"] + ), .library( name: "PacketTunnelProvider", - targets: ["PacketTunnelProvider"]), + targets: ["PacketTunnelProvider"] + ), ], dependencies: [ .package(url: "https://github.com/CocoaLumberjack/CocoaLumberjack.git", from: "3.7.4"), .package(url: "https://github.com/getsentry/sentry-cocoa", from: "7.31.3"), ], targets: [ + .target( + name: "OutlineLauncher", + dependencies: + ["CocoaLumberjack", + .product(name: "CocoaLumberjackSwift", package: "CocoaLumberjack"), + "OutlineCatalystApp"] + ), + .target( + name: "OutlineCatalystApp", + dependencies: [ + "OutlineAppKitBridge", + .product(name: "CocoaLumberjackSwift", package: "CocoaLumberjack"), + ] + ), + .target( + name: "OutlineAppKitBridge", + dependencies: [ + .product(name: "CocoaLumberjackSwift", package: "CocoaLumberjack"), + "OutlineNotification", + ] + ), .target( name: "PacketTunnelProvider", dependencies: - ["CocoaLumberjack", - .product(name: "CocoaLumberjackSwift", package: "CocoaLumberjack"), - "Tun2socks", - "OutlineTunnel" - ], + ["CocoaLumberjack", + .product(name: "CocoaLumberjackSwift", package: "CocoaLumberjack"), + "Tun2socks", + "OutlineTunnel"], cSettings: [ .headerSearchPath("Internal"), ] ), + .target(name: "OutlineNotification"), .target( name: "OutlineSentryLogger", dependencies: [ .product(name: "CocoaLumberjackSwift", package: "CocoaLumberjack"), - .product(name: "Sentry", package: "sentry-cocoa") + .product(name: "Sentry", package: "sentry-cocoa"), ] ), .target( name: "OutlineTunnel", dependencies: [ .product(name: "CocoaLumberjackSwift", package: "CocoaLumberjack"), + "Tun2socks", ] ), .binaryTarget( @@ -50,6 +82,7 @@ let package = Package( ), .testTarget( name: "OutlineTunnelTest", - dependencies: ["OutlineTunnel", "PacketTunnelProvider"]), + dependencies: ["OutlineTunnel", "PacketTunnelProvider"] + ), ] ) diff --git a/src/cordova/apple/OutlineAppleLib/README.md b/src/cordova/apple/OutlineAppleLib/README.md index cca89c18fe6..51fb8089e7c 100644 --- a/src/cordova/apple/OutlineAppleLib/README.md +++ b/src/cordova/apple/OutlineAppleLib/README.md @@ -1,3 +1,4 @@ -# OutlineTun2Socks +# OutlineAppleLib -This package provides the Outline Tun2socks framework as a Swift Package. +This package provides all Outline Apple logic, including the Outline Tun2socks +framework, as a Swift Package. diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/AppKitBridge.swift b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/AppKitBridge.swift new file mode 100644 index 00000000000..9067e14b040 --- /dev/null +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/AppKitBridge.swift @@ -0,0 +1,83 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#if os(macOS) + import AppKit + import CocoaLumberjackSwift + import ServiceManagement + + public class AppKitBridge: NSObject, AppKitBridgeProtocol { + private var statusItemController: StatusItemController? + static let kAppGroup = "QT8Z3Q9V3A.org.outline.macos.client" + static let kAppLauncherName = "launcher3" + + override public required init() { + super.init() + } + + /// Terminates the application. + @objc public func terminate() { + NSApp.terminate(self) + } + + /// Set the connection status in the app's menu in the system-wide menu bar. + @objc public func setConnectionStatus(_ status: ConnectionStatus) { + if statusItemController == nil { + DDLogInfo("[AppKitBridge] No status item controller found. Creating one now.") + statusItemController = StatusItemController() + } + statusItemController!.setStatus(status: status) + } + + /// Enables or disables the embedded app launcher as a login item. + @objc public func setAppLauncherEnabled(_ isEnabled: Bool) { + guard let launcherBundleId = getLauncherBundleId() else { + return DDLogError("[AppKitBridge] Unable to set launcher for missing bundle ID.") + } + + if !SMLoginItemSetEnabled(launcherBundleId as! CFString, isEnabled) { + return DDLogError("[AppKitBridge] Failed to set enable=\(isEnabled) for launcher \(launcherBundleId).") + } + + return DDLogInfo("[AppKitBridge] Successfully set enable=\(isEnabled) for launcher \(launcherBundleId).") + } + + /// Loads the main application from a given launcher bundle. + @objc public func loadMainApp(_ launcherBundleId: String) { + // Retrieve the main app's bundle ID programmatically from the embedded launcher bundle ID. + let mainAppBundleId = getMainBundleId(launcherBundleId) + DDLogInfo("[AppKitBridge] Loading main app \(mainAppBundleId) from launcher \(launcherBundleId).") + + let descriptor = NSAppleEventDescriptor(string: launcherBundleId) + NSWorkspace.shared.launchApplication(withBundleIdentifier: mainAppBundleId, + options: [.withoutActivation, .andHide], + additionalEventParamDescriptor: descriptor, + launchIdentifier: nil) + } + } + + /// Returns the embedded launcher application's bundle ID. + private func getLauncherBundleId() -> String? { + guard let bundleId = Bundle.main.bundleIdentifier else { + DDLogError("[AppKitBridge] Failed to retrieve the application's bundle ID.") + return nil + } + return String(format: "%@.%@", bundleId, AppKitBridge.kAppLauncherName) + } + + /// Returns the main application's bundle ID from the embedded launcher bundle ID. + private func getMainBundleId(_ launcherBundleId: String) -> String { + return (launcherBundleId as NSString).deletingPathExtension + } +#endif diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/AppKitBridgeProtocol.swift b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/AppKitBridgeProtocol.swift new file mode 100644 index 00000000000..2df694d8cc0 --- /dev/null +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/AppKitBridgeProtocol.swift @@ -0,0 +1,28 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Foundation + +@objc +public protocol AppKitBridgeProtocol: NSObjectProtocol { + init() + + func terminate() + + func setConnectionStatus(_ status: ConnectionStatus) + + func setAppLauncherEnabled(_ isEnabled: Bool) + + func loadMainApp(_ launcherBundleId: String) +} diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/ConnectionStatus.swift b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/ConnectionStatus.swift new file mode 100644 index 00000000000..bf0171db456 --- /dev/null +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/ConnectionStatus.swift @@ -0,0 +1,19 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +@objc public enum ConnectionStatus: Int { + case unknown + case connected + case disconnected +} diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/Contents.json b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/Contents.json new file mode 100644 index 00000000000..73c00596a7f --- /dev/null +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/status_bar_button_image.imageset/Contents.json b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/status_bar_button_image.imageset/Contents.json new file mode 100644 index 00000000000..27d38b248ed --- /dev/null +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/status_bar_button_image.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "outline-black-off-2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/status_bar_button_image.imageset/outline-black-off-2x.png b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Assets.xcassets/status_bar_button_image.imageset/outline-black-off-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4785b8a26f5c3f6e76321fa399156fd5ff41f004 GIT binary patch literal 578 zcmV-I0=@l-P){)?CRw64`A}f)VD_8F0tmF|^B9WCy zB(ky+i5t!=69~;uvowW!4yH+(uQ!v)1Y%~qTJQe>Aff_5319)BW9DtIeFZ@Jv;Ypw z+&M4tC<%gyJ^)kz=1$|i3I&v3MMMIzW9Gfn(^3?Ih~#B;!sHAcYq~ zgYaQ7bHmI(5`+mb*SW3`x(qpj(5(3yKx}IkW?5_}vc>^3pO|?w0J6M75K)=S1&_9o zr4cs@{mCm#SjF=2!3^%_^l@_wRP1@NYU zAOvnPvesx{J^&+=H(JyL6@{>1#6odKwy(LB`@Tw`#ddQmPfCEV|9=9&8T3c2Ww-TUOmB>GtmQqyCUz^kK;*X2xHmDkVTfH4$xzs3D>Q5rt?z=y;>+>O@Hn zVhK+GtN}CtPO^L;&%=H4JDO+RxAyd(_gaGk#czh`*{vi* zS^&X3FB$kH&>Bjnl3;adLSz(}8cbq=$4m%K#Y*(YK^tesZUTWX0H4Wd3L&x|jb3Ta ztUDridI8`<>AuZrS$kP#;-r zJ#j5j=;pR}#|5+Hq=-bpN3JWa0jtDV^P+LIg-UC~qG0B|qyJ1|R1FtI_6{j7$PxubY#Ucm&t#Uk zB=o~P0(})-qMzuxb8Amxg`~&S&dS?OXIT z%UjeSB-W7(k~?MelG5yuahaEO*|%pbfB*jkfFEFJvO)@kHDdq(002ovPDHLkV1no4 B`3nF5 literal 0 HcmV?d00001 diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift new file mode 100644 index 00000000000..90308f96af0 --- /dev/null +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift @@ -0,0 +1,101 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#if os(macOS) + import AppKit + import CocoaLumberjackSwift + import OutlineNotification + + var StatusItem = NSStatusItem() + + class StatusItemController: NSObject { + let connectionStatusMenuItem = NSMenuItem(title: MenuTitle.statusDisconnected, + action: nil, + keyEquivalent: "") + + private enum AppIconImage { + static let statusConnected = getImage(name: "status_bar_button_image_connected") + static let statusDisconnected = getImage(name: "status_bar_button_image") + } + + // TODO: Internationalize these user-facing strings. + private enum MenuTitle { + static let open = "Open" + static let quit = "Quit" + static let statusConnected = "Connected" + static let statusDisconnected = "Disconnected" + } + + override init() { + super.init() + + DDLogInfo("[StatusItemController] Creating status menu") + StatusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength) + setStatus(status: .disconnected) + + let menu = NSMenu() + let openMenuItem = NSMenuItem(title: MenuTitle.open, action: #selector(openApplication), keyEquivalent: "o") + openMenuItem.target = self + menu.addItem(openMenuItem) + menu.addItem(connectionStatusMenuItem) + menu.addItem(NSMenuItem.separator()) + let closeMenuItem = NSMenuItem(title: MenuTitle.quit, action: #selector(closeApplication), keyEquivalent: "q") + closeMenuItem.target = self + menu.addItem(closeMenuItem) + StatusItem.menu = menu + } + + func setStatus(status: ConnectionStatus) { + let isConnected = status == .connected + let appIconImage = isConnected ? AppIconImage.statusConnected : AppIconImage.statusDisconnected + appIconImage.isTemplate = true + StatusItem.button?.image = appIconImage + + let connectionStatusTitle = isConnected ? MenuTitle.statusConnected : MenuTitle.statusDisconnected + connectionStatusMenuItem.title = connectionStatusTitle + } + + @objc func openApplication(_: AnyObject?) { + DDLogInfo("[StatusItemController] Opening application") + NSApp.activate(ignoringOtherApps: true) + guard let uiWindow = getUiWindow() else { + return + } + uiWindow.makeKeyAndOrderFront(self) + } + + @objc func closeApplication(_: AnyObject?) { + DDLogInfo("[StatusItemController] Closing application") + NotificationCenter.default.post(name: .kAppQuit, object: nil) + NSApplication.shared.terminate(self) + } + } + + private func getUiWindow() -> NSWindow? { + for window in NSApp.windows { + if String(describing: window).contains("UINSWindow") { + return window + } + } + return nil + } + + private func getImage(name: String) -> NSImage { + guard let image = Bundle.module.image(forResource: NSImage.Name(name)) else { + fatalError("Unable to load image asset named \(name).") + } + return image + } + +#endif diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineCatalystApp/AppKitBundleLoader.swift b/src/cordova/apple/OutlineAppleLib/Sources/OutlineCatalystApp/AppKitBundleLoader.swift new file mode 100644 index 00000000000..a98024d9e9b --- /dev/null +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineCatalystApp/AppKitBundleLoader.swift @@ -0,0 +1,37 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import CocoaLumberjackSwift +import Foundation +import OutlineAppKitBridge + +enum BridgeBundle { + static let fileName = "AppKitBridge.bundle" + static let className = "OutlineAppKitBridge.AppKitBridge" +} + +public func createAppKitBridge() -> AppKitBridgeProtocol { + guard let bundleURL = Bundle.main.builtInPlugInsURL?.appendingPathComponent(BridgeBundle.fileName) else { + preconditionFailure("[AppKitBundleLoader] \(BridgeBundle.fileName) should exist") + } + guard let bundle = Bundle(url: bundleURL) else { + preconditionFailure("[AppKitBundleLoader] \(BridgeBundle.fileName) should exist") + } + DDLogInfo("[AppKitBundleLoader] AppKit bundle loaded successfully") + let className = BridgeBundle.className + guard let appKitBridgeClass = bundle.classNamed(className) as? AppKitBridgeProtocol.Type else { + preconditionFailure("[AppKitBundleLoader] Cannot initialise \(className) from \(BridgeBundle.fileName)") + } + return appKitBridgeClass.init() +} diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineCatalystApp/OutlineCatalystApp.swift b/src/cordova/apple/OutlineAppleLib/Sources/OutlineCatalystApp/OutlineCatalystApp.swift new file mode 100644 index 00000000000..a9624eb190d --- /dev/null +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineCatalystApp/OutlineCatalystApp.swift @@ -0,0 +1,61 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#if targetEnvironment(macCatalyst) + import CocoaLumberjack + import CocoaLumberjackSwift + import Foundation + import OutlineAppKitBridge + import OutlineNotification + import ServiceManagement + + @objcMembers + public class OutlineCatalystApp: NSObject { + public static func initApp() { + DDLog.add(DDOSLogger.sharedInstance) + + let appKitBridge: AppKitBridgeProtocol = createAppKitBridge() + + // Configure the window. + let scenes = UIApplication.shared.connectedScenes + for scene in scenes { + let windowScene = (scene as! UIWindowScene) + windowScene.titlebar?.titleVisibility = .hidden + windowScene.titlebar?.toolbar = nil + windowScene.sizeRestrictions?.minimumSize = CGSizeMake(400, 550) + windowScene.sizeRestrictions?.maximumSize = CGSizeMake(400, 550) + } + + // Initiate the connection status menu in unknown state by default. + // TODO: Check status in case the the VPN is already running. + appKitBridge.setConnectionStatus(.unknown) + + NotificationCenter.default.addObserver(forName: NSNotification.kVpnConnected, + object: nil, + queue: nil) + { _ in + appKitBridge.setConnectionStatus(.connected) + } + NotificationCenter.default.addObserver(forName: NSNotification.kVpnDisconnected, + object: nil, + queue: nil) + { _ in + appKitBridge.setConnectionStatus(.disconnected) + } + + // Enable app launcher to start on boot. + appKitBridge.setAppLauncherEnabled(true) + } + } +#endif diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineLauncher/AppDelegate.swift b/src/cordova/apple/OutlineAppleLib/Sources/OutlineLauncher/AppDelegate.swift new file mode 100644 index 00000000000..06aafc23b2c --- /dev/null +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineLauncher/AppDelegate.swift @@ -0,0 +1,64 @@ +// Copyright 2018 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#if targetEnvironment(macCatalyst) + import CocoaLumberjack + import CocoaLumberjackSwift + import NetworkExtension + import OutlineCatalystApp + import UIKit + + @UIApplicationMain + class AppDelegate: UIResponder, UIApplicationDelegate { + func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + DDLog.add(DDOSLogger.sharedInstance) + + let appKitBridge = createAppKitBridge() + shouldLaunchMainApp { shouldLaunch in + defer { + DDLogInfo("Exiting launcher...") + appKitBridge.terminate() + } + if !shouldLaunch { + DDLogInfo("Not launching, Outline not connected at shutdown") + return + } + DDLogInfo("Outline connected at shutdown. Launching") + + guard let launcherBundleId = Bundle.main.bundleIdentifier else { + DDLogError("Failed to retrieve the bundle ID for the launcher app.") + return + } + appKitBridge.loadMainApp(launcherBundleId) + } + return true + } + + // Returns whether the launcher should launch the main app. + private func shouldLaunchMainApp(completion: @escaping (Bool) -> Void) { + NETunnelProviderManager.loadAllFromPreferences { managers, error in + guard error == nil, managers != nil else { + DDLogError("Failed to get tunnel manager: \(String(describing: error))") + return completion(false) + } + guard let manager: NETunnelProviderManager = managers!.first, managers!.count > 0 else { + DDLogError("No tunnel managers found.") + return completion(false) + } + DDLogInfo("Tunnel manager found.") + return completion(manager.isOnDemandEnabled) + } + } + } +#endif diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineNotification/NSNotification+Outline.swift b/src/cordova/apple/OutlineAppleLib/Sources/OutlineNotification/NSNotification+Outline.swift new file mode 100644 index 00000000000..72e168e2770 --- /dev/null +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineNotification/NSNotification+Outline.swift @@ -0,0 +1,30 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Foundation + +// TODO: Move this to a better location and clean up where notifications get +// sent and consumed. + +public extension Notification.Name { + static let kAppQuit = Notification.Name("appQuit") + static let kVpnConnected = Notification.Name("vpnConnected") + static let kVpnDisconnected = Notification.Name("vpnDisconnected") +} + +@objc public extension NSNotification { + static let kAppQuit = Notification.Name.kAppQuit + static let kVpnConnected = Notification.Name.kVpnConnected + static let kVpnDisconnected = Notification.Name.kVpnDisconnected +} diff --git a/src/cordova/apple/OutlineAppleLib/Sources/PacketTunnelProvider/PacketTunnelProvider.m b/src/cordova/apple/OutlineAppleLib/Sources/PacketTunnelProvider/PacketTunnelProvider.m index 621196ed239..8dea141f95c 100644 --- a/src/cordova/apple/OutlineAppleLib/Sources/PacketTunnelProvider/PacketTunnelProvider.m +++ b/src/cordova/apple/OutlineAppleLib/Sources/PacketTunnelProvider/PacketTunnelProvider.m @@ -49,10 +49,10 @@ @implementation PacketTunnelProvider - (id)init { self = [super init]; -#if TARGET_OS_IPHONE - NSString *appGroup = @"group.org.outline.ios.client"; -#else +#if (TARGET_OS_OSX || TARGET_OS_MACCATALYST) NSString *appGroup = @"QT8Z3Q9V3A.org.outline.macos.client"; +#else + NSString *appGroup = @"group.org.outline.ios.client"; #endif NSURL *containerUrl = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:appGroup]; diff --git a/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj b/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj index 1a0c2cc6e86..429ab77cf84 100755 --- a/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj +++ b/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 0207DA581B56EA530066E2B4 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0207DA571B56EA530066E2B4 /* Images.xcassets */; }; + 0207DA581B56EA530066E2B4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0207DA571B56EA530066E2B4 /* Assets.xcassets */; }; 1273B4E700B84E31B2528701 /* CDVClipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 91E45572BB494E9299D2DD41 /* CDVClipboard.m */; }; 1CE7466BA73B4CCB838EBE21 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 941052A220F54953928FF2E2 /* libz.tbd */; }; 1D3623260D0F684500981E51 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* AppDelegate.m */; }; @@ -16,14 +16,22 @@ 301BF552109A68D80062928A /* libCordova.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 301BF535109A57CC0062928A /* libCordova.a */; }; 302D95F114D2391D003F00A1 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 302D95EF14D2391D003F00A1 /* MainViewController.m */; }; 302D95F214D2391D003F00A1 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 302D95F014D2391D003F00A1 /* MainViewController.xib */; }; - 3B0347531F212F0200C8EF1F /* VpnExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 3B0347481F212F0100C8EF1F /* VpnExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 52CBB892295BD8F200D0073F /* CocoaLumberjack in Frameworks */ = {isa = PBXBuildFile; productRef = 52CBB891295BD8F200D0073F /* CocoaLumberjack */; }; - 52CBB894295BD8F200D0073F /* CocoaLumberjackSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 52CBB893295BD8F200D0073F /* CocoaLumberjackSwift */; }; + 3B0347531F212F0200C8EF1F /* VpnExtension.appex in Embed App Extensions (2 items) */ = {isa = PBXBuildFile; fileRef = 3B0347481F212F0100C8EF1F /* VpnExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 52CE53E7295B6A310064D03D /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 52CE53E6295B6A310064D03D /* Sentry */; }; 52E783062A5880CF00355E64 /* PacketTunnelProvider in Frameworks */ = {isa = PBXBuildFile; productRef = 52E783052A5880CF00355E64 /* PacketTunnelProvider */; }; 5F7F90AE0E924FD7B065C415 /* CDVStatusBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 0394302BA6114B2AB648D4FF /* CDVStatusBar.m */; }; 6AFF5BF91D6E424B00AB3073 /* CDVLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */; }; - F63DC2182970AFFA00D92E0A /* OutlineAppleLib in Frameworks */ = {isa = PBXBuildFile; productRef = F63DC2172970AFFA00D92E0A /* OutlineAppleLib */; }; + A271D4202A7069D8009981B2 /* OutlineLauncher in Frameworks */ = {isa = PBXBuildFile; productRef = A271D41F2A7069D8009981B2 /* OutlineLauncher */; }; + A271D4222A706CB9009981B2 /* OutlineAppKitBridge in Frameworks */ = {isa = PBXBuildFile; productRef = A271D4212A706CB9009981B2 /* OutlineAppKitBridge */; }; + A271D42D2A708240009981B2 /* AppDelegate+Outline.m in Sources */ = {isa = PBXBuildFile; fileRef = A271D42C2A708240009981B2 /* AppDelegate+Outline.m */; }; + A271D4302A708278009981B2 /* CocoaLumberjack in Frameworks */ = {isa = PBXBuildFile; productRef = A271D42F2A708278009981B2 /* CocoaLumberjack */; }; + A271D4322A708278009981B2 /* CocoaLumberjackSwift in Frameworks */ = {isa = PBXBuildFile; productRef = A271D4312A708278009981B2 /* CocoaLumberjackSwift */; }; + A271D4342A70829D009981B2 /* OutlineAppleLib in Frameworks */ = {isa = PBXBuildFile; productRef = A271D4332A70829D009981B2 /* OutlineAppleLib */; }; + A27F43AA29F6EC43002C3678 /* config.xml in CopyFiles */ = {isa = PBXBuildFile; fileRef = F840E1F0165FE0F500CFE078 /* config.xml */; }; + A27F43AB29F6EC43002C3678 /* www in CopyFiles */ = {isa = PBXBuildFile; fileRef = 301BF56E109A69640062928A /* www */; }; + A2A83B392A1C5B2E00755F56 /* OutlineLauncher.app in Copy OutlineLauncher */ = {isa = PBXBuildFile; fileRef = A26D262D2A1C41B1009838E0 /* OutlineLauncher.app */; platformFilter = maccatalyst; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + A2B8C14D2A58B70E0054487E /* AppKitBridge.bundle in Embed PlugIns */ = {isa = PBXBuildFile; fileRef = A2DBB2F62A00D2DD0017E696 /* AppKitBridge.bundle */; platformFilter = maccatalyst; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + A2DBB2FB2A00D2F90017E696 /* AppKitBridge.bundle in Embed App Extensions (2 items) */ = {isa = PBXBuildFile; fileRef = A2DBB2F62A00D2DD0017E696 /* AppKitBridge.bundle */; platformFilter = maccatalyst; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; FC8C310B1FAA814A004262BE /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FC8C310A1FAA814A004262BE /* NetworkExtension.framework */; }; FC8C310C1FAA88FB004262BE /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FC8C310A1FAA814A004262BE /* NetworkExtension.framework */; }; /* End PBXBuildFile section */ @@ -57,35 +65,80 @@ remoteGlobalIDString = C0C01EB21E3911D50056E6CB; remoteInfo = Cordova; }; + A2B8C14E2A58B70E0054487E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = A2DBB2F52A00D2DD0017E696; + remoteInfo = AppKitBridge; + }; + A2DBB3032A00D5F90017E696 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = A2DBB2F52A00D2DD0017E696; + remoteInfo = AppKitBridge; + }; + A2F6068D2A1C6D4A0039183A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = A26D262C2A1C41B1009838E0; + remoteInfo = OutlineLauncher; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 3B0347571F212F0200C8EF1F /* Embed App Extensions */ = { + 3B0347571F212F0200C8EF1F /* Embed App Extensions (2 items) */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 13; files = ( - 3B0347531F212F0200C8EF1F /* VpnExtension.appex in Embed App Extensions */, + A2DBB2FB2A00D2F90017E696 /* AppKitBridge.bundle in Embed App Extensions (2 items) */, + 3B0347531F212F0200C8EF1F /* VpnExtension.appex in Embed App Extensions (2 items) */, + ); + name = "Embed App Extensions (2 items)"; + runOnlyForDeploymentPostprocessing = 0; + }; + A27F43A929F6EC1C002C3678 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 7; + files = ( + A27F43AA29F6EC43002C3678 /* config.xml in CopyFiles */, + A27F43AB29F6EC43002C3678 /* www in CopyFiles */, ); - name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; }; - 3B0347691F21321500C8EF1F /* Embed Frameworks */ = { + A2A83B382A1C5B0C00755F56 /* Copy OutlineLauncher */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = Contents/Library/LoginItems; + dstSubfolderSpec = 1; + files = ( + A2A83B392A1C5B2E00755F56 /* OutlineLauncher.app in Copy OutlineLauncher */, + ); + name = "Copy OutlineLauncher"; + runOnlyForDeploymentPostprocessing = 0; + }; + A2B8C1502A58B70E0054487E /* Embed PlugIns */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; - dstSubfolderSpec = 10; + dstSubfolderSpec = 13; files = ( + A2B8C14D2A58B70E0054487E /* AppKitBridge.bundle in Embed PlugIns */, ); - name = "Embed Frameworks"; + name = "Embed PlugIns"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 0168F53D3AFF46F5B346C874 /* CDVStatusBar.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVStatusBar.h; path = "cordova-plugin-statusbar/CDVStatusBar.h"; sourceTree = ""; }; - 0207DA571B56EA530066E2B4 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Outline/Images.xcassets; sourceTree = SOURCE_ROOT; }; + 0207DA571B56EA530066E2B4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Outline/Assets.xcassets; sourceTree = SOURCE_ROOT; }; 0394302BA6114B2AB648D4FF /* CDVStatusBar.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVStatusBar.m; path = "cordova-plugin-statusbar/CDVStatusBar.m"; sourceTree = ""; }; 1D3623240D0F684500981E51 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 1D3623250D0F684500981E51 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -108,6 +161,11 @@ 91E45572BB494E9299D2DD41 /* CDVClipboard.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVClipboard.m; path = "cordova-plugin-clipboard/CDVClipboard.m"; sourceTree = ""; }; 936C2951B7544BC8A20B6746 /* CDVClipboard.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVClipboard.h; path = "cordova-plugin-clipboard/CDVClipboard.h"; sourceTree = ""; }; 941052A220F54953928FF2E2 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + A26D262D2A1C41B1009838E0 /* OutlineLauncher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OutlineLauncher.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A26D26382A1C41B4009838E0 /* OutlineLauncher.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OutlineLauncher.entitlements; sourceTree = ""; }; + A271D42C2A708240009981B2 /* AppDelegate+Outline.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "AppDelegate+Outline.m"; sourceTree = ""; }; + A271D42E2A708253009981B2 /* AppDelegate+Outline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AppDelegate+Outline.h"; sourceTree = ""; }; + A2DBB2F62A00D2DD0017E696 /* AppKitBridge.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AppKitBridge.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; AAFAFA54943F490EAF4CD5BC /* OutlinePlugin.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = OutlinePlugin.swift; path = "cordova-plugin-outline/OutlinePlugin.swift"; sourceTree = ""; }; EB87FDF31871DA8E0020F90C /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; name = www; path = ../../www; sourceTree = ""; }; EB87FDF41871DAF40020F90C /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = ../../config.xml; sourceTree = ""; }; @@ -123,12 +181,12 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + A271D4302A708278009981B2 /* CocoaLumberjack in Frameworks */, 301BF552109A68D80062928A /* libCordova.a in Frameworks */, FC8C310C1FAA88FB004262BE /* NetworkExtension.framework in Frameworks */, - 52CBB894295BD8F200D0073F /* CocoaLumberjackSwift in Frameworks */, + A271D4322A708278009981B2 /* CocoaLumberjackSwift in Frameworks */, + A271D4342A70829D009981B2 /* OutlineAppleLib in Frameworks */, 52CE53E7295B6A310064D03D /* Sentry in Frameworks */, - F63DC2182970AFFA00D92E0A /* OutlineAppleLib in Frameworks */, - 52CBB892295BD8F200D0073F /* CocoaLumberjack in Frameworks */, 1CE7466BA73B4CCB838EBE21 /* libz.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -142,6 +200,22 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A26D262A2A1C41B1009838E0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A271D4202A7069D8009981B2 /* OutlineLauncher in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A2DBB2F32A00D2DD0017E696 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A271D4222A706CB9009981B2 /* OutlineAppKitBridge in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -153,6 +227,8 @@ 302D95F014D2391D003F00A1 /* MainViewController.xib */, 1D3623240D0F684500981E51 /* AppDelegate.h */, 1D3623250D0F684500981E51 /* AppDelegate.m */, + A271D42C2A708240009981B2 /* AppDelegate+Outline.m */, + A271D42E2A708253009981B2 /* AppDelegate+Outline.h */, ); name = Classes; path = Outline/Classes; @@ -163,6 +239,8 @@ children = ( 1D6058910D05DD3D006BFB54 /* Outline.app */, 3B0347481F212F0100C8EF1F /* VpnExtension.appex */, + A2DBB2F62A00D2DD0017E696 /* AppKitBridge.bundle */, + A26D262D2A1C41B1009838E0 /* OutlineLauncher.app */, ); name = Products; sourceTree = ""; @@ -181,6 +259,7 @@ 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, 3B0347491F212F0200C8EF1F /* VpnExtension */, + A26D262E2A1C41B1009838E0 /* OutlineLauncher */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, ); @@ -202,7 +281,7 @@ isa = PBXGroup; children = ( FC55AB411F4F960A0056F12C /* VpnExtension-Info.plist */, - 0207DA571B56EA530066E2B4 /* Images.xcassets */, + 0207DA571B56EA530066E2B4 /* Assets.xcassets */, 3047A50E1AB8057F00498E2A /* config */, 8D1107310486CEB800E47090 /* Outline-Info.plist */, 6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */, @@ -261,6 +340,14 @@ path = Outline/Resources/vpn; sourceTree = ""; }; + A26D262E2A1C41B1009838E0 /* OutlineLauncher */ = { + isa = PBXGroup; + children = ( + A26D26382A1C41B4009838E0 /* OutlineLauncher.entitlements */, + ); + path = OutlineLauncher; + sourceTree = ""; + }; EB87FDF11871DA420020F90C /* Staging */ = { isa = PBXGroup; children = ( @@ -285,26 +372,28 @@ isa = PBXNativeTarget; buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "Outline" */; buildPhases = ( - 304B58A110DAC018002A0835 /* Copy www directory */, + A27F43A929F6EC1C002C3678 /* CopyFiles */, 1D60588D0D05DD3D006BFB54 /* Resources */, 1D60588E0D05DD3D006BFB54 /* Sources */, 1D60588F0D05DD3D006BFB54 /* Frameworks */, - 3B0347571F212F0200C8EF1F /* Embed App Extensions */, - 3B0347691F21321500C8EF1F /* Embed Frameworks */, + A2A83B382A1C5B0C00755F56 /* Copy OutlineLauncher */, + 3B0347571F212F0200C8EF1F /* Embed App Extensions (2 items) */, FC0FFD6C1FCCE21E00EB0129 /* Remove unused framework architectures */, ); buildRules = ( ); dependencies = ( + A2F6068E2A1C6D4A0039183A /* PBXTargetDependency */, + A2DBB3042A00D5F90017E696 /* PBXTargetDependency */, 301BF551109A68C00062928A /* PBXTargetDependency */, 3B0347521F212F0200C8EF1F /* PBXTargetDependency */, ); name = Outline; packageProductDependencies = ( 52CE53E6295B6A310064D03D /* Sentry */, - 52CBB891295BD8F200D0073F /* CocoaLumberjack */, - 52CBB893295BD8F200D0073F /* CocoaLumberjackSwift */, - F63DC2172970AFFA00D92E0A /* OutlineAppleLib */, + A271D42F2A708278009981B2 /* CocoaLumberjack */, + A271D4312A708278009981B2 /* CocoaLumberjackSwift */, + A271D4332A70829D009981B2 /* OutlineAppleLib */, ); productName = Outline; productReference = 1D6058910D05DD3D006BFB54 /* Outline.app */; @@ -316,7 +405,6 @@ buildPhases = ( 3B0347441F212F0100C8EF1F /* Sources */, 3B0347451F212F0100C8EF1F /* Frameworks */, - 3B0347461F212F0100C8EF1F /* Resources */, ); buildRules = ( ); @@ -330,12 +418,53 @@ productReference = 3B0347481F212F0100C8EF1F /* VpnExtension.appex */; productType = "com.apple.product-type.app-extension"; }; + A26D262C2A1C41B1009838E0 /* OutlineLauncher */ = { + isa = PBXNativeTarget; + buildConfigurationList = A26D26392A1C41B4009838E0 /* Build configuration list for PBXNativeTarget "OutlineLauncher" */; + buildPhases = ( + A25EB8812A8437D700B92EE0 /* Sources */, + A26D262A2A1C41B1009838E0 /* Frameworks */, + A2B8C1502A58B70E0054487E /* Embed PlugIns */, + ); + buildRules = ( + ); + dependencies = ( + A2B8C14F2A58B70E0054487E /* PBXTargetDependency */, + ); + name = OutlineLauncher; + packageProductDependencies = ( + A271D41F2A7069D8009981B2 /* OutlineLauncher */, + ); + productName = OutlineLauncher; + productReference = A26D262D2A1C41B1009838E0 /* OutlineLauncher.app */; + productType = "com.apple.product-type.application"; + }; + A2DBB2F52A00D2DD0017E696 /* AppKitBridge */ = { + isa = PBXNativeTarget; + buildConfigurationList = A2DBB2F72A00D2DD0017E696 /* Build configuration list for PBXNativeTarget "AppKitBridge" */; + buildPhases = ( + A2DBB2F22A00D2DD0017E696 /* Sources */, + A2DBB2F32A00D2DD0017E696 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AppKitBridge; + packageProductDependencies = ( + A271D4212A706CB9009981B2 /* OutlineAppKitBridge */, + ); + productName = AppKitBridge; + productReference = A2DBB2F62A00D2DD0017E696 /* AppKitBridge.bundle */; + productType = "com.apple.product-type.bundle"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 1430; LastUpgradeCheck = 1010; TargetAttributes = { 1D6058900D05DD3D006BFB54 = { @@ -355,6 +484,13 @@ }; }; }; + A26D262C2A1C41B1009838E0 = { + CreatedOnToolsVersion = 14.3; + }; + A2DBB2F52A00D2DD0017E696 = { + CreatedOnToolsVersion = 14.3; + LastSwiftMigration = 1430; + }; }; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Outline" */; @@ -382,6 +518,8 @@ targets = ( 1D6058900D05DD3D006BFB54 /* Outline */, 3B0347471F212F0100C8EF1F /* VpnExtension */, + A2DBB2F52A00D2DD0017E696 /* AppKitBridge */, + A26D262C2A1C41B1009838E0 /* OutlineLauncher */, ); }; /* End PBXProject section */ @@ -409,36 +547,14 @@ buildActionMask = 2147483647; files = ( 302D95F214D2391D003F00A1 /* MainViewController.xib in Resources */, - 0207DA581B56EA530066E2B4 /* Images.xcassets in Resources */, + 0207DA581B56EA530066E2B4 /* Assets.xcassets in Resources */, 6AFF5BF91D6E424B00AB3073 /* CDVLaunchScreen.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 3B0347461F212F0100C8EF1F /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 304B58A110DAC018002A0835 /* Copy www directory */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Copy www directory"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"$SRCROOT/Outline/Scripts/copy-www-build-step.sh\"\n"; - showEnvVarsInLog = 0; - }; FC0FFD6C1FCCE21E00EB0129 /* Remove unused framework architectures */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -466,6 +582,7 @@ 5F7F90AE0E924FD7B065C415 /* CDVStatusBar.m in Sources */, 2A617D29B96942E58B082FAC /* OutlinePlugin.swift in Sources */, 1273B4E700B84E31B2528701 /* CDVClipboard.m in Sources */, + A271D42D2A708240009981B2 /* AppDelegate+Outline.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -476,6 +593,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A25EB8812A8437D700B92EE0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A2DBB2F22A00D2DD0017E696 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -489,6 +620,24 @@ target = 3B0347471F212F0100C8EF1F /* VpnExtension */; targetProxy = 3B0347511F212F0200C8EF1F /* PBXContainerItemProxy */; }; + A2B8C14F2A58B70E0054487E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + platformFilter = maccatalyst; + target = A2DBB2F52A00D2DD0017E696 /* AppKitBridge */; + targetProxy = A2B8C14E2A58B70E0054487E /* PBXContainerItemProxy */; + }; + A2DBB3042A00D5F90017E696 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + platformFilter = maccatalyst; + target = A2DBB2F52A00D2DD0017E696 /* AppKitBridge */; + targetProxy = A2DBB3032A00D5F90017E696 /* PBXContainerItemProxy */; + }; + A2F6068E2A1C6D4A0039183A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + platformFilter = maccatalyst; + target = A26D262C2A1C41B1009838E0 /* OutlineLauncher */; + targetProxy = A2F6068D2A1C6D4A0039183A /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -525,13 +674,17 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.outline.ios.client; + "PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]" = org.outline.macos.client; PRODUCT_NAME = Outline; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = iphoneos; STRIP_BITCODE_FROM_COPIED_FILES = NO; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = YES; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,6"; VALIDATE_WORKSPACE = NO; }; name = Debug; @@ -568,12 +721,16 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.outline.ios.client; + "PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]" = org.outline.macos.client; PRODUCT_NAME = Outline; PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = iphoneos; STRIP_BITCODE_FROM_COPIED_FILES = NO; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = YES; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,6"; VALIDATE_WORKSPACE = NO; }; name = Release; @@ -623,10 +780,12 @@ ); MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = org.outline.ios.client.VpnExtension; + "PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]" = org.outline.macos.client.VpnExtension; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; STRIP_BITCODE_FROM_COPIED_FILES = NO; + SUPPORTS_MACCATALYST = YES; SWIFT_INSTALL_OBJC_HEADER = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -673,10 +832,12 @@ ); MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = org.outline.ios.client.VpnExtension; + "PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]" = org.outline.macos.client.VpnExtension; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; STRIP_BITCODE_FROM_COPIED_FILES = NO; + SUPPORTS_MACCATALYST = YES; SWIFT_INSTALL_OBJC_HEADER = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -684,6 +845,208 @@ }; name = Release; }; + A26D263A2A1C41B4009838E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = OutlineLauncher/OutlineLauncher.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = QT8Z3Q9V3A; + ENABLE_HARDENED_RUNTIME = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_LSApplicationCategoryType = ""; + INFOPLIST_KEY_LSBackgroundOnly = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.3; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = org.outline.macos.client.launcher3; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = YES; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 2; + }; + name = Debug; + }; + A26D263B2A1C41B4009838E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = OutlineLauncher/OutlineLauncher.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = QT8Z3Q9V3A; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_LSApplicationCategoryType = ""; + INFOPLIST_KEY_LSBackgroundOnly = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.3; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = org.outline.macos.client.launcher3; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = YES; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 2; + }; + name = Release; + }; + A2DBB2F82A00D2DD0017E696 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = QT8Z3Q9V3A; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSPrincipalClass = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + MACOSX_DEPLOYMENT_TARGET = 13.3; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = org.outline.macos.client.AppKitBridge; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Outline/Classes/AppKitBridge/AppKitBridge-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + A2DBB2F92A00D2DD0017E696 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = QT8Z3Q9V3A; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSPrincipalClass = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + MACOSX_DEPLOYMENT_TARGET = 13.3; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = org.outline.macos.client.AppKitBridge; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Outline/Classes/AppKitBridge/AppKitBridge-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 3047A5111AB8059700498E2A /* build.xcconfig */; @@ -720,6 +1083,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SKIP_INSTALL = NO; @@ -762,6 +1126,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; SDKROOT = iphoneos; SKIP_INSTALL = NO; SWIFT_COMPILATION_MODE = wholemodule; @@ -789,6 +1154,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + A26D26392A1C41B4009838E0 /* Build configuration list for PBXNativeTarget "OutlineLauncher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A26D263A2A1C41B4009838E0 /* Debug */, + A26D263B2A1C41B4009838E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A2DBB2F72A00D2DD0017E696 /* Build configuration list for PBXNativeTarget "AppKitBridge" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A2DBB2F82A00D2DD0017E696 /* Debug */, + A2DBB2F92A00D2DD0017E696 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Outline" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -820,16 +1203,6 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 52CBB891295BD8F200D0073F /* CocoaLumberjack */ = { - isa = XCSwiftPackageProductDependency; - package = 52CBB890295BD8F200D0073F /* XCRemoteSwiftPackageReference "CocoaLumberjack" */; - productName = CocoaLumberjack; - }; - 52CBB893295BD8F200D0073F /* CocoaLumberjackSwift */ = { - isa = XCSwiftPackageProductDependency; - package = 52CBB890295BD8F200D0073F /* XCRemoteSwiftPackageReference "CocoaLumberjack" */; - productName = CocoaLumberjackSwift; - }; 52CE53E6295B6A310064D03D /* Sentry */ = { isa = XCSwiftPackageProductDependency; package = 52CE53E5295B6A310064D03D /* XCRemoteSwiftPackageReference "sentry-cocoa" */; @@ -839,7 +1212,25 @@ isa = XCSwiftPackageProductDependency; productName = PacketTunnelProvider; }; - F63DC2172970AFFA00D92E0A /* OutlineAppleLib */ = { + A271D41F2A7069D8009981B2 /* OutlineLauncher */ = { + isa = XCSwiftPackageProductDependency; + productName = OutlineLauncher; + }; + A271D4212A706CB9009981B2 /* OutlineAppKitBridge */ = { + isa = XCSwiftPackageProductDependency; + productName = OutlineAppKitBridge; + }; + A271D42F2A708278009981B2 /* CocoaLumberjack */ = { + isa = XCSwiftPackageProductDependency; + package = 52CBB890295BD8F200D0073F /* XCRemoteSwiftPackageReference "CocoaLumberjack" */; + productName = CocoaLumberjack; + }; + A271D4312A708278009981B2 /* CocoaLumberjackSwift */ = { + isa = XCSwiftPackageProductDependency; + package = 52CBB890295BD8F200D0073F /* XCRemoteSwiftPackageReference "CocoaLumberjack" */; + productName = CocoaLumberjackSwift; + }; + A271D4332A70829D009981B2 /* OutlineAppleLib */ = { isa = XCSwiftPackageProductDependency; productName = OutlineAppleLib; }; diff --git a/src/cordova/apple/xcode/ios/Outline/Classes/AppDelegate+Outline.h b/src/cordova/apple/xcode/ios/Outline/Classes/AppDelegate+Outline.h new file mode 100644 index 00000000000..0b0d77f0b2f --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Classes/AppDelegate+Outline.h @@ -0,0 +1,24 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef AppDelegate_Outline_h +#define AppDelegate_Outline_h + +#import "AppDelegate.h" + +@interface AppDelegate (Outline) +@end + +#endif /* AppDelegate_Outline_h */ + diff --git a/src/cordova/apple/xcode/ios/Outline/Classes/AppDelegate+Outline.m b/src/cordova/apple/xcode/ios/Outline/Classes/AppDelegate+Outline.m new file mode 100644 index 00000000000..65c7e999b7d --- /dev/null +++ b/src/cordova/apple/xcode/ios/Outline/Classes/AppDelegate+Outline.m @@ -0,0 +1,41 @@ +// Copyright 2023 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import "AppDelegate+Outline.h" +#import "Outline-Swift.h" + +#if TARGET_OS_MACCATALYST +@import OutlineCatalystApp; +@import ServiceManagement; +#endif + +@implementation AppDelegate (Outline) + +#pragma mark - Lifecycle + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions: + (NSDictionary *)launchOptions { +#if TARGET_OS_MACCATALYST + [OutlineCatalystApp initApp]; +#endif + + [super application:application didFinishLaunchingWithOptions:launchOptions]; + + return YES; +} + +@end diff --git a/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist b/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist index e0cfd597c96..22020f35c0f 100644 --- a/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist +++ b/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist @@ -40,6 +40,8 @@ ITSAppUsesNonExemptEncryption + LSUIElement + NSAppTransportSecurity NSAllowsArbitraryLoads diff --git a/src/cordova/apple/xcode/ios/Outline/Outline.entitlements b/src/cordova/apple/xcode/ios/Outline/Outline.entitlements index 6e3d6122da3..9d88e9d506e 100644 --- a/src/cordova/apple/xcode/ios/Outline/Outline.entitlements +++ b/src/cordova/apple/xcode/ios/Outline/Outline.entitlements @@ -6,9 +6,13 @@ packet-tunnel-provider + com.apple.security.app-sandbox + com.apple.security.application-groups group.org.outline.ios.client + com.apple.security.network.client + diff --git a/src/cordova/apple/xcode/ios/Outline/VpnExtension.entitlements b/src/cordova/apple/xcode/ios/Outline/VpnExtension.entitlements index 6e3d6122da3..fb4bf1a906d 100644 --- a/src/cordova/apple/xcode/ios/Outline/VpnExtension.entitlements +++ b/src/cordova/apple/xcode/ios/Outline/VpnExtension.entitlements @@ -6,9 +6,15 @@ packet-tunnel-provider + com.apple.security.app-sandbox + com.apple.security.application-groups group.org.outline.ios.client + com.apple.security.network.client + + com.apple.security.network.server + diff --git a/src/cordova/apple/xcode/ios/OutlineLauncher/OutlineLauncher.entitlements b/src/cordova/apple/xcode/ios/OutlineLauncher/OutlineLauncher.entitlements new file mode 100644 index 00000000000..bd0f3175861 --- /dev/null +++ b/src/cordova/apple/xcode/ios/OutlineLauncher/OutlineLauncher.entitlements @@ -0,0 +1,18 @@ + + + + + com.apple.developer.networking.networkextension + + packet-tunnel-provider + + com.apple.security.app-sandbox + + com.apple.security.application-groups + + $(TeamIdentifierPrefix)org.outline.macos.client + + com.apple.security.files.user-selected.read-only + + + diff --git a/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m b/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m index 6c681b5f9d3..2769ab40121 100644 --- a/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m +++ b/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m @@ -16,6 +16,7 @@ #import "Outline-Swift.h" @import ServiceManagement; +@import OutlineNotification; @import OutlineTunnel; @interface AppDelegate() @@ -55,13 +56,13 @@ - (void)applicationWillFinishLaunching:(NSNotification *)aNotification { usingBlock:^(NSNotification *_Nonnull n) { self.isSystemShuttingDown = YES; }]; - [NSNotificationCenter.defaultCenter addObserverForName:OutlinePlugin.kVpnConnectedNotification + [NSNotificationCenter.defaultCenter addObserverForName:NSNotification.kVpnConnected object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { [self setAppIcon:@"StatusBarButtonImageConnected"]; }]; - [NSNotificationCenter.defaultCenter addObserverForName:OutlinePlugin.kVpnDisconnectedNotification + [NSNotificationCenter.defaultCenter addObserverForName:NSNotification.kVpnDisconnected object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { @@ -111,7 +112,7 @@ - (void)applicationWillTerminate:(NSNotification *)notification { if (!self.isSystemShuttingDown) { // Don't post a quit notification if the system is shutting down so the VPN is not stopped // and it auto-connects on startup. - [[NSNotificationCenter defaultCenter] postNotificationName:OutlinePlugin.kAppQuitNotification + [[NSNotificationCenter defaultCenter] postNotificationName:NSNotification.kAppQuit object:nil]; } } diff --git a/src/cordova/plugin/apple/src/OutlinePlugin.swift b/src/cordova/plugin/apple/src/OutlinePlugin.swift index 9248154be70..f6ff6ef9c5b 100644 --- a/src/cordova/plugin/apple/src/OutlinePlugin.swift +++ b/src/cordova/plugin/apple/src/OutlinePlugin.swift @@ -18,29 +18,30 @@ import NetworkExtension import Sentry import OutlineSentryLogger +import OutlineNotification import OutlineTunnel @objcMembers class OutlinePlugin: CDVPlugin { - + private enum Action { - static let start = "start" - static let stop = "stop" - static let onStatusChange = "onStatusChange" + static let start = "start" + static let stop = "stop" + static let onStatusChange = "onStatusChange" } - - public static let kAppQuitNotification = "outlinePluginAppQuitNotification" - public static let kVpnConnectedNotification = "outlineVpnConnected" - public static let kVpnDisconnectedNotification = "outlineVpnDisconnected" - public static let kMaxBreadcrumbs: Int = 100 - + + public static let kMaxBreadcrumbs: UInt = 100 + private var sentryLogger: OutlineSentryLogger! private var callbacks: [String: String]! - + #if os(macOS) // cordova-osx does not support URL interception. Until it does, we have version-controlled // AppDelegate.m (intercept) and Outline-Info.plist (register protocol) to handle ss:// URLs. private var urlHandler: CDVMacOsUrlHandler? +#endif +#if os(macOS) || targetEnvironment(macCatalyst) + private static let kPlatform = "macOS" private static let kAppGroup = "QT8Z3Q9V3A.org.outline.macos.client" #else @@ -51,22 +52,25 @@ class OutlinePlugin: CDVPlugin { override func pluginInitialize() { self.sentryLogger = OutlineSentryLogger(forAppGroup: OutlinePlugin.kAppGroup) callbacks = [String: String]() - + OutlineVpn.shared.onVpnStatusChange(onVpnStatusChange) - + #if os(macOS) self.urlHandler = CDVMacOsUrlHandler.init(self.webView) +#endif + +#if os(macOS) || targetEnvironment(macCatalyst) NotificationCenter.default.addObserver( self, selector: #selector(self.stopVpnOnAppQuit), - name: NSNotification.Name(rawValue: OutlinePlugin.kAppQuitNotification), + name: .kAppQuit, object: nil) #endif - + #if os(iOS) self.migrateLocalStorage() #endif } - + /** Starts the VPN. This method is idempotent for a given tunnel. - Parameters: @@ -87,9 +91,8 @@ class OutlinePlugin: CDVPlugin { } OutlineVpn.shared.start(tunnelId, configJson:configJson) { errorCode in if errorCode == OutlineVpn.ErrorCode.noError { -#if os(macOS) - NotificationCenter.default.post( - name: NSNotification.Name(rawValue: OutlinePlugin.kVpnConnectedNotification), object: nil) +#if os(macOS) || targetEnvironment(macCatalyst) + NotificationCenter.default.post(name: .kVpnConnected, object: nil) #endif self.sendSuccess(callbackId: command.callbackId) } else { @@ -98,7 +101,7 @@ class OutlinePlugin: CDVPlugin { } } } - + /** Stops the VPN. Sends an error if the given tunnel is not running. - Parameters: @@ -112,12 +115,11 @@ class OutlinePlugin: CDVPlugin { DDLogInfo("\(Action.stop) \(tunnelId)") OutlineVpn.shared.stop(tunnelId) sendSuccess(callbackId: command.callbackId) -#if os(macOS) - NotificationCenter.default.post( - name: NSNotification.Name(rawValue: OutlinePlugin.kVpnDisconnectedNotification), object: nil) +#if os(macOS) || targetEnvironment(macCatalyst) + NotificationCenter.default.post(name: .kVpnDisconnected, object: nil) #endif } - + func isRunning(_ command: CDVInvokedUrlCommand) { guard let tunnelId = command.argument(at: 0) as? String else { return sendError("Missing tunnel ID", callbackId: command.callbackId) @@ -125,7 +127,7 @@ class OutlinePlugin: CDVPlugin { DDLogInfo("isRunning \(tunnelId)") sendSuccess(OutlineVpn.shared.isActive(tunnelId), callbackId: command.callbackId) } - + func onStatusChange(_ command: CDVInvokedUrlCommand) { guard let tunnelId = command.argument(at: 0) as? String else { return sendError("Missing tunnel ID", callbackId: command.callbackId) @@ -133,9 +135,9 @@ class OutlinePlugin: CDVPlugin { DDLogInfo("\(Action.onStatusChange) \(tunnelId)") setCallbackId(command.callbackId!, action: Action.onStatusChange, tunnelId: tunnelId) } - + // MARK: Error reporting - + func initializeErrorReporting(_ command: CDVInvokedUrlCommand) { DDLogInfo("initializeErrorReporting") guard let sentryDsn = command.argument(at: 0) as? String else { @@ -160,7 +162,7 @@ class OutlinePlugin: CDVPlugin { } sendSuccess(true, callbackId: command.callbackId) } - + func reportEvents(_ command: CDVInvokedUrlCommand) { var uuid: String if let eventId = command.argument(at: 0) as? String { @@ -172,76 +174,74 @@ class OutlinePlugin: CDVPlugin { } else { uuid = NSUUID().uuidString } - self.sentryLogger.addVpnExtensionLogsToSentry(maxBreadcrumbsToAdd: OutlinePlugin.kMaxBreadcrumbs / 2) + self.sentryLogger.addVpnExtensionLogsToSentry(maxBreadcrumbsToAdd: Int(OutlinePlugin.kMaxBreadcrumbs / 2)) SentrySDK.capture(message: "\(OutlinePlugin.kPlatform) report (\(uuid))") { scope in scope.setLevel(.info) } self.sendSuccess(true, callbackId: command.callbackId) } - + #if os(macOS) func quitApplication(_ command: CDVInvokedUrlCommand) { NSApplication.shared.terminate(self) } #endif - - // MARK: Helpers - - @objc private func stopVpnOnAppQuit() { - if let activeTunnelId = OutlineVpn.shared.activeTunnelId { - OutlineVpn.shared.stop(activeTunnelId) - } + + // MARK: Helpers + + @objc private func stopVpnOnAppQuit() { + if let activeTunnelId = OutlineVpn.shared.activeTunnelId { + OutlineVpn.shared.stop(activeTunnelId) } - - // Receives NEVPNStatusDidChange notifications. Calls onTunnelStatusChange for the active - // tunnel. - func onVpnStatusChange(vpnStatus: NEVPNStatus, tunnelId: String) { - var tunnelStatus: Int - switch vpnStatus { - case .connected: -#if os(macOS) - NotificationCenter.default.post( - name: NSNotification.Name(rawValue: OutlinePlugin.kVpnConnectedNotification), object: nil) + } + + // Receives NEVPNStatusDidChange notifications. Calls onTunnelStatusChange for the active + // tunnel. + func onVpnStatusChange(vpnStatus: NEVPNStatus, tunnelId: String) { + var tunnelStatus: Int + switch vpnStatus { + case .connected: +#if os(macOS) || targetEnvironment(macCatalyst) + NotificationCenter.default.post(name: .kVpnConnected, object: nil) #endif - tunnelStatus = OutlineTunnel.TunnelStatus.connected.rawValue - case .disconnected: -#if os(macOS) - NotificationCenter.default.post( - name: NSNotification.Name(rawValue: OutlinePlugin.kVpnDisconnectedNotification), object: nil) + tunnelStatus = OutlineTunnel.TunnelStatus.connected.rawValue + case .disconnected: +#if os(macOS) || targetEnvironment(macCatalyst) + NotificationCenter.default.post(name: .kVpnDisconnected, object: nil) #endif - tunnelStatus = OutlineTunnel.TunnelStatus.disconnected.rawValue - case .reasserting: - tunnelStatus = OutlineTunnel.TunnelStatus.reconnecting.rawValue - default: - return; // Do not report transient or invalid states. - } - DDLogDebug("Calling onStatusChange (\(tunnelStatus)) for tunnel \(tunnelId)") - if let callbackId = getCallbackIdFor(action: Action.onStatusChange, - tunnelId: tunnelId, - keepCallback: true) { - let result = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: Int32(tunnelStatus)) - send(pluginResult: result, callbackId: callbackId, keepCallback: true) - } + tunnelStatus = OutlineTunnel.TunnelStatus.disconnected.rawValue + case .reasserting: + tunnelStatus = OutlineTunnel.TunnelStatus.reconnecting.rawValue + default: + return; // Do not report transient or invalid states. + } + DDLogDebug("Calling onStatusChange (\(tunnelStatus)) for tunnel \(tunnelId)") + if let callbackId = getCallbackIdFor(action: Action.onStatusChange, + tunnelId: tunnelId, + keepCallback: true) { + let result = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: Int32(tunnelStatus)) + send(pluginResult: result, callbackId: callbackId, keepCallback: true) } - - // Returns whether |config| contains all the expected keys - private func containsExpectedKeys(_ configJson: [String: Any]?) -> Bool { - return configJson?["host"] != nil && configJson?["port"] != nil && + } + + // Returns whether |config| contains all the expected keys + private func containsExpectedKeys(_ configJson: [String: Any]?) -> Bool { + return configJson?["host"] != nil && configJson?["port"] != nil && configJson?["password"] != nil && configJson?["method"] != nil } - + // MARK: Callback helpers - + private func sendSuccess(callbackId: String, keepCallback: Bool = false) { let result = CDVPluginResult(status: CDVCommandStatus_OK) send(pluginResult: result, callbackId: callbackId, keepCallback: keepCallback) } - + private func sendSuccess(_ operationResult: Bool, callbackId: String, keepCallback: Bool = false) { let result = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: operationResult) send(pluginResult: result, callbackId: callbackId, keepCallback: keepCallback) } - + private func sendError(_ message: String, callbackId: String, errorCode: OutlineVpn.ErrorCode = OutlineVpn.ErrorCode.undefined, keepCallback: Bool = false) { @@ -250,7 +250,7 @@ class OutlinePlugin: CDVPlugin { messageAs: Int32(errorCode.rawValue)) send(pluginResult: result, callbackId: callbackId, keepCallback: keepCallback) } - + private func send(pluginResult: CDVPluginResult?, callbackId: String, keepCallback: Bool) { guard let result = pluginResult else { return DDLogWarn("Missing plugin result"); @@ -258,13 +258,13 @@ class OutlinePlugin: CDVPlugin { result.setKeepCallbackAs(keepCallback) self.commandDelegate?.send(result, callbackId: callbackId) } - + // Maps |action| and |tunnelId| to |callbackId| in the callbacks dictionary. private func setCallbackId(_ callbackId: String, action: String, tunnelId: String) { DDLogDebug("\(action):\(tunnelId):\(callbackId)") callbacks["\(action):\(tunnelId)"] = callbackId } - + // Retrieves the callback ID for |action| and |tunnelId|. Unmaps the entry if |keepCallback| // is false. private func getCallbackIdFor(action: String, tunnelId: String?, @@ -282,67 +282,75 @@ class OutlinePlugin: CDVPlugin { } return callbackId } - + // Migrates local storage files from UIWebView to WKWebView. private func migrateLocalStorage() { - // Local storage backing files have the following naming format: $scheme_$hostname_$port.localstorage - // With UIWebView, the app used the file:// scheme with no hostname and any port. - let kUIWebViewLocalStorageFilename = "file__0.localstorage" - // With WKWebView, the app uses the app:// scheme with localhost as a hostname and any port. - let kWKWebViewLocalStorageFilename = "app_localhost_0.localstorage" - - let fileManager = FileManager.default - let appLibraryDir = fileManager.urls(for: .libraryDirectory, in: .userDomainMask)[0] - - var uiWebViewLocalStorageDir: URL + // Local storage backing files have the following naming format: $scheme_$hostname_$port.localstorage + // With UIWebView, the app used the file:// scheme with no hostname and any port. + let kUIWebViewLocalStorageFilename = "file__0.localstorage" + // With WKWebView, the app uses the app:// scheme with localhost as a hostname and any port. + let kWKWebViewLocalStorageFilename = "app_localhost_0.localstorage" + + let fileManager = FileManager.default + let appLibraryDir = fileManager.urls(for: .libraryDirectory, in: .userDomainMask)[0] + + let uiWebViewLocalStorageDir: URL +#if targetEnvironment(macCatalyst) + guard let bundleID = Bundle.main.bundleIdentifier else { + return DDLogError("Unable to get bundleID for app.") + } + let appSupportDir = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0] + uiWebViewLocalStorageDir = appSupportDir.appendingPathComponent(bundleID) +#else if fileManager.fileExists(atPath: appLibraryDir.appendingPathComponent( "WebKit/LocalStorage/\(kUIWebViewLocalStorageFilename)").relativePath) { - uiWebViewLocalStorageDir = appLibraryDir.appendingPathComponent("WebKit/LocalStorage") + uiWebViewLocalStorageDir = appLibraryDir.appendingPathComponent("WebKit/LocalStorage") } else { - uiWebViewLocalStorageDir = appLibraryDir.appendingPathComponent("Caches") - } - let uiWebViewLocalStorage = uiWebViewLocalStorageDir.appendingPathComponent(kUIWebViewLocalStorageFilename) - if !fileManager.fileExists(atPath: uiWebViewLocalStorage.relativePath) { - return DDLogInfo("Not migrating, UIWebView local storage files missing.") - } - - let wkWebViewLocalStorageDir = appLibraryDir.appendingPathComponent("WebKit/WebsiteData/LocalStorage/") - let wkWebViewLocalStorage = wkWebViewLocalStorageDir.appendingPathComponent(kWKWebViewLocalStorageFilename) - // Only copy the local storage files if they don't exist for WKWebView. - if fileManager.fileExists(atPath: wkWebViewLocalStorage.relativePath) { - return DDLogInfo("Not migrating, WKWebView local storage files present.") - } - DDLogInfo("Migrating UIWebView local storage to WKWebView") - - // Create the WKWebView local storage directory; this is safe if the directory already exists. - do { - try fileManager.createDirectory(at: wkWebViewLocalStorageDir, withIntermediateDirectories: true) - } catch { - return DDLogError("Failed to create WKWebView local storage directory") - } - - // Create a tmp directory and copy onto it the local storage files. - guard let tmpDir = try? fileManager.url(for: .itemReplacementDirectory, in: .userDomainMask, - appropriateFor: wkWebViewLocalStorage, create: true) else { - return DDLogError("Failed to create tmp dir") - } - do { - try fileManager.copyItem(at: uiWebViewLocalStorage, - to: tmpDir.appendingPathComponent(wkWebViewLocalStorage.lastPathComponent)) - try fileManager.copyItem(at: URL.init(fileURLWithPath: "\(uiWebViewLocalStorage.relativePath)-shm"), - to: tmpDir.appendingPathComponent("\(kWKWebViewLocalStorageFilename)-shm")) - try fileManager.copyItem(at: URL.init(fileURLWithPath: "\(uiWebViewLocalStorage.relativePath)-wal"), - to: tmpDir.appendingPathComponent("\(kWKWebViewLocalStorageFilename)-wal")) - } catch { - return DDLogError("Local storage migration failed.") - } - - // Atomically move the tmp directory to the WKWebView local storage directory. - guard let _ = try? fileManager.replaceItemAt(wkWebViewLocalStorageDir, withItemAt: tmpDir, - backupItemName: nil, options: .usingNewMetadataOnly) else { - return DDLogError("Failed to copy tmp dir to WKWebView local storage dir") + uiWebViewLocalStorageDir = appLibraryDir.appendingPathComponent("Caches") } - - DDLogInfo("Local storage migration succeeded") +#endif + let uiWebViewLocalStorage = uiWebViewLocalStorageDir.appendingPathComponent(kUIWebViewLocalStorageFilename) + if !fileManager.fileExists(atPath: uiWebViewLocalStorage.relativePath) { + return DDLogInfo("Not migrating, UIWebView local storage files missing.") + } + + let wkWebViewLocalStorageDir = appLibraryDir.appendingPathComponent("WebKit/WebsiteData/LocalStorage/") + let wkWebViewLocalStorage = wkWebViewLocalStorageDir.appendingPathComponent(kWKWebViewLocalStorageFilename) + // Only copy the local storage files if they don't exist for WKWebView. + if fileManager.fileExists(atPath: wkWebViewLocalStorage.relativePath) { + return DDLogInfo("Not migrating, WKWebView local storage files present.") + } + DDLogInfo("Migrating UIWebView local storage to WKWebView") + + // Create the WKWebView local storage directory; this is safe if the directory already exists. + do { + try fileManager.createDirectory(at: wkWebViewLocalStorageDir, withIntermediateDirectories: true) + } catch { + return DDLogError("Failed to create WKWebView local storage directory") + } + + // Create a tmp directory and copy onto it the local storage files. + guard let tmpDir = try? fileManager.url(for: .itemReplacementDirectory, in: .userDomainMask, + appropriateFor: wkWebViewLocalStorage, create: true) else { + return DDLogError("Failed to create tmp dir") + } + do { + try fileManager.copyItem(at: uiWebViewLocalStorage, + to: tmpDir.appendingPathComponent(wkWebViewLocalStorage.lastPathComponent)) + try fileManager.copyItem(at: URL.init(fileURLWithPath: "\(uiWebViewLocalStorage.relativePath)-shm"), + to: tmpDir.appendingPathComponent("\(kWKWebViewLocalStorageFilename)-shm")) + try fileManager.copyItem(at: URL.init(fileURLWithPath: "\(uiWebViewLocalStorage.relativePath)-wal"), + to: tmpDir.appendingPathComponent("\(kWKWebViewLocalStorageFilename)-wal")) + } catch { + return DDLogError("Local storage migration failed.") + } + + // Atomically move the tmp directory to the WKWebView local storage directory. + guard let _ = try? fileManager.replaceItemAt(wkWebViewLocalStorageDir, withItemAt: tmpDir, + backupItemName: nil, options: .usingNewMetadataOnly) else { + return DDLogError("Failed to copy tmp dir to WKWebView local storage dir") + } + + DDLogInfo("Local storage migration succeeded") } -} + } From cdfd9a99d18c9ed3bfb3d40c1ff5612d790767e5 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Thu, 17 Aug 2023 11:42:05 -0400 Subject: [PATCH 10/15] Revert "Force npm to use global installed node-gyp." This reverts commit 6db878eebb83223b23a79f473787f8b60e000102. --- .github/workflows/build_and_test_debug.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_and_test_debug.yml b/.github/workflows/build_and_test_debug.yml index b1520800a6b..90f50238270 100644 --- a/.github/workflows/build_and_test_debug.yml +++ b/.github/workflows/build_and_test_debug.yml @@ -108,10 +108,10 @@ jobs: node-version: 18 cache: npm - - name: Force npm to use global installed node-gyp - run: | # https://github.com/nodejs/node-gyp/blob/main/docs/Force-npm-to-use-global-node-gyp.md - npm install --global node-gyp@latest - npm config set node_gyp $(npm prefix -g)/lib/node_modules/node-gyp/bin/node-gyp.js + - name: Update the npm-bundled version of node-gyp + run: | # https://github.com/nodejs/node-gyp/blob/main/docs/Updating-npm-bundled-node-gyp.md + npm -v + npm explore npm/node_modules/@npmcli/run-script -g -- npm_config_global=false npm install node-gyp@latest - name: Install NPM Dependencies run: npm ci From 960e59559fbdfd1ea87a0078a1947612640e5d2d Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Thu, 17 Aug 2023 11:42:11 -0400 Subject: [PATCH 11/15] Revert "Update the npm-bundled version of node-gyp." This reverts commit f771fd837d34f1e7ae9d8384818509be95428538. --- .github/workflows/build_and_test_debug.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/build_and_test_debug.yml b/.github/workflows/build_and_test_debug.yml index 90f50238270..e028a99bd41 100644 --- a/.github/workflows/build_and_test_debug.yml +++ b/.github/workflows/build_and_test_debug.yml @@ -108,11 +108,6 @@ jobs: node-version: 18 cache: npm - - name: Update the npm-bundled version of node-gyp - run: | # https://github.com/nodejs/node-gyp/blob/main/docs/Updating-npm-bundled-node-gyp.md - npm -v - npm explore npm/node_modules/@npmcli/run-script -g -- npm_config_global=false npm install node-gyp@latest - - name: Install NPM Dependencies run: npm ci From 8725477a40cad23ab31460171e490829613f87f2 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Thu, 17 Aug 2023 13:19:05 -0400 Subject: [PATCH 12/15] Fix locales for Chinese Simplified and Traditional. --- src/cordova/android/import_messages.mjs | 10 +++++----- src/cordova/apple/import_messages.mjs | 13 ++++++++++++- .../Localizable.strings | 0 .../Localizable.strings | 0 4 files changed, 17 insertions(+), 6 deletions(-) rename src/cordova/apple/xcode/ios/Outline/Resources/{zh-CN.lproj => zh-Hans.lproj}/Localizable.strings (100%) rename src/cordova/apple/xcode/ios/Outline/Resources/{zh-TW.lproj => zh-Hant.lproj}/Localizable.strings (100%) diff --git a/src/cordova/android/import_messages.mjs b/src/cordova/android/import_messages.mjs index f85f5596f67..14faab98f47 100644 --- a/src/cordova/android/import_messages.mjs +++ b/src/cordova/android/import_messages.mjs @@ -30,14 +30,14 @@ function escapeXmlCharacters(str) { .replace(/&/g, '\\&'); } -function getNativeLocale(polymerLang) { - switch (polymerLang) { +function getNativeLocale(locale) { + switch (locale) { case 'es-419': return 'es'; case 'sr-Latn': return 'b+sr+Latn'; default: - return polymerLang.replace('-', '-r'); + return locale.replace('-', '-r'); } } @@ -46,8 +46,8 @@ function getNativeLocale(polymerLang) { * @param {string} locale A locale for which to get a strings filepath. * @returns {string} The filepath. */ -export function getStringsFilepath(polymerLang) { - const localeSuffix = polymerLang ? `-${getNativeLocale(polymerLang)}` : ''; +export function getStringsFilepath(locale) { + const localeSuffix = locale ? `-${getNativeLocale(locale)}` : ''; return path.join(...STRINGS_DIR, `values${localeSuffix}`, STRINGS_FILENAME); } diff --git a/src/cordova/apple/import_messages.mjs b/src/cordova/apple/import_messages.mjs index a858aa35d3c..c1dd0f1a200 100644 --- a/src/cordova/apple/import_messages.mjs +++ b/src/cordova/apple/import_messages.mjs @@ -18,13 +18,24 @@ import I18N from 'i18n-strings-files'; const STRINGS_DIR = ['src', 'cordova', 'apple', 'xcode', 'ios', 'Outline', 'Resources']; const STRINGS_FILENAME = 'Localizable.strings'; +function getNativeLocale(locale) { + switch (locale) { + case 'zh-CN': + return 'zh-Hans'; + case 'zh-TW': + return 'zh-Hant'; + default: + return locale; + } +} + /** * Retrieves a filepath for a given locale to read/write strings to. * @param {string} locale A locale for which to get a strings filepath. * @returns {string} The filepath. */ export function getStringsFilepath(locale) { - return path.join(...STRINGS_DIR, `${locale}.lproj`, STRINGS_FILENAME); + return path.join(...STRINGS_DIR, `${getNativeLocale(locale)}.lproj`, STRINGS_FILENAME); } /** diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/zh-CN.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/zh-Hans.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/zh-CN.lproj/Localizable.strings rename to src/cordova/apple/xcode/ios/Outline/Resources/zh-Hans.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/zh-TW.lproj/Localizable.strings b/src/cordova/apple/xcode/ios/Outline/Resources/zh-Hant.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/zh-TW.lproj/Localizable.strings rename to src/cordova/apple/xcode/ios/Outline/Resources/zh-Hant.lproj/Localizable.strings From f96953599a25066e601d0ccea8e5ed4dcf994a26 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Thu, 17 Aug 2023 13:20:50 -0400 Subject: [PATCH 13/15] Add the localization files to the iOS project. --- .../ios/Outline.xcodeproj/project.pbxproj | 214 +++++++++++++++++- .../xcode/ios/Outline/Outline-Info.plist | 14 +- .../xcode/ios/Outline/VpnExtension-Info.plist | 14 +- 3 files changed, 226 insertions(+), 16 deletions(-) diff --git a/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj b/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj index 429ab77cf84..9a832f8e289 100755 --- a/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj +++ b/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 52E783062A5880CF00355E64 /* PacketTunnelProvider in Frameworks */ = {isa = PBXBuildFile; productRef = 52E783052A5880CF00355E64 /* PacketTunnelProvider */; }; 5F7F90AE0E924FD7B065C415 /* CDVStatusBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 0394302BA6114B2AB648D4FF /* CDVStatusBar.m */; }; 6AFF5BF91D6E424B00AB3073 /* CDVLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */; }; + A2580F052A8E8CDD0010CEFA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A2580EC22A8E8CDA0010CEFA /* Localizable.strings */; }; A271D4202A7069D8009981B2 /* OutlineLauncher in Frameworks */ = {isa = PBXBuildFile; productRef = A271D41F2A7069D8009981B2 /* OutlineLauncher */; }; A271D4222A706CB9009981B2 /* OutlineAppKitBridge in Frameworks */ = {isa = PBXBuildFile; productRef = A271D4212A706CB9009981B2 /* OutlineAppKitBridge */; }; A271D42D2A708240009981B2 /* AppDelegate+Outline.m in Sources */ = {isa = PBXBuildFile; fileRef = A271D42C2A708240009981B2 /* AppDelegate+Outline.m */; }; @@ -161,6 +162,72 @@ 91E45572BB494E9299D2DD41 /* CDVClipboard.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVClipboard.m; path = "cordova-plugin-clipboard/CDVClipboard.m"; sourceTree = ""; }; 936C2951B7544BC8A20B6746 /* CDVClipboard.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVClipboard.h; path = "cordova-plugin-clipboard/CDVClipboard.h"; sourceTree = ""; }; 941052A220F54953928FF2E2 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + A2580EC32A8E8CDA0010CEFA /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = ""; }; + A2580EC42A8E8CDA0010CEFA /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = ""; }; + A2580EC52A8E8CDA0010CEFA /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; + A2580EC62A8E8CDA0010CEFA /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Localizable.strings; sourceTree = ""; }; + A2580EC72A8E8CDA0010CEFA /* mn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mn; path = mn.lproj/Localizable.strings; sourceTree = ""; }; + A2580EC82A8E8CDA0010CEFA /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = ""; }; + A2580EC92A8E8CDA0010CEFA /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Localizable.strings; sourceTree = ""; }; + A2580ECA2A8E8CDA0010CEFA /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Localizable.strings; sourceTree = ""; }; + A2580ECB2A8E8CDA0010CEFA /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = ""; }; + A2580ECC2A8E8CDA0010CEFA /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/Localizable.strings; sourceTree = ""; }; + A2580ECD2A8E8CDA0010CEFA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + A2580ECE2A8E8CDA0010CEFA /* ka */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ka; path = ka.lproj/Localizable.strings; sourceTree = ""; }; + A2580ECF2A8E8CDA0010CEFA /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; + A2580ED02A8E8CDB0010CEFA /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/Localizable.strings; sourceTree = ""; }; + A2580ED12A8E8CDB0010CEFA /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; + A2580ED22A8E8CDB0010CEFA /* no */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = no; path = no.lproj/Localizable.strings; sourceTree = ""; }; + A2580ED32A8E8CDB0010CEFA /* sr-Latn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sr-Latn"; path = "sr-Latn.lproj/Localizable.strings"; sourceTree = ""; }; + A2580ED42A8E8CDB0010CEFA /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = sq.lproj/Localizable.strings; sourceTree = ""; }; + A2580ED52A8E8CDB0010CEFA /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; + A2580ED62A8E8CDB0010CEFA /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = ""; }; + A2580ED72A8E8CDB0010CEFA /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = ""; }; + A2580ED82A8E8CDB0010CEFA /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/Localizable.strings; sourceTree = ""; }; + A2580ED92A8E8CDB0010CEFA /* hi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hi; path = hi.lproj/Localizable.strings; sourceTree = ""; }; + A2580EDA2A8E8CDB0010CEFA /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/Localizable.strings; sourceTree = ""; }; + A2580EDB2A8E8CDB0010CEFA /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = ""; }; + A2580EDC2A8E8CDB0010CEFA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; + A2580EDD2A8E8CDB0010CEFA /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = ""; }; + A2580EDE2A8E8CDB0010CEFA /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; + A2580EDF2A8E8CDB0010CEFA /* sw */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sw; path = sw.lproj/Localizable.strings; sourceTree = ""; }; + A2580EE02A8E8CDB0010CEFA /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = ""; }; + A2580EE12A8E8CDB0010CEFA /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Localizable.strings; sourceTree = ""; }; + A2580EE22A8E8CDB0010CEFA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Localizable.strings; sourceTree = ""; }; + A2580EE32A8E8CDB0010CEFA /* sr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sr; path = sr.lproj/Localizable.strings; sourceTree = ""; }; + A2580EE42A8E8CDB0010CEFA /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = ""; }; + A2580EE52A8E8CDB0010CEFA /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; + A2580EE62A8E8CDB0010CEFA /* az */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = az; path = az.lproj/Localizable.strings; sourceTree = ""; }; + A2580EE72A8E8CDB0010CEFA /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = ""; }; + A2580EE82A8E8CDB0010CEFA /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = ""; }; + A2580EE92A8E8CDB0010CEFA /* lt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lt; path = lt.lproj/Localizable.strings; sourceTree = ""; }; + A2580EEA2A8E8CDC0010CEFA /* mk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mk; path = mk.lproj/Localizable.strings; sourceTree = ""; }; + A2580EEB2A8E8CDC0010CEFA /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = ""; }; + A2580EEC2A8E8CDC0010CEFA /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/Localizable.strings; sourceTree = ""; }; + A2580EED2A8E8CDC0010CEFA /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = ""; }; + A2580EEE2A8E8CDC0010CEFA /* mr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mr; path = mr.lproj/Localizable.strings; sourceTree = ""; }; + A2580EEF2A8E8CDC0010CEFA /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/Localizable.strings; sourceTree = ""; }; + A2580EF02A8E8CDC0010CEFA /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; + A2580EF12A8E8CDC0010CEFA /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/Localizable.strings; sourceTree = ""; }; + A2580EF22A8E8CDC0010CEFA /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/Localizable.strings; sourceTree = ""; }; + A2580EF32A8E8CDC0010CEFA /* lv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lv; path = lv.lproj/Localizable.strings; sourceTree = ""; }; + A2580EF42A8E8CDC0010CEFA /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/Localizable.strings; sourceTree = ""; }; + A2580EF52A8E8CDC0010CEFA /* ta */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ta; path = ta.lproj/Localizable.strings; sourceTree = ""; }; + A2580EF62A8E8CDC0010CEFA /* am */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = am; path = am.lproj/Localizable.strings; sourceTree = ""; }; + A2580EF72A8E8CDC0010CEFA /* bn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bn; path = bn.lproj/Localizable.strings; sourceTree = ""; }; + A2580EF82A8E8CDC0010CEFA /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; + A2580EF92A8E8CDC0010CEFA /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = ""; }; + A2580EFA2A8E8CDC0010CEFA /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = ""; }; + A2580EFB2A8E8CDC0010CEFA /* af */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = af; path = af.lproj/Localizable.strings; sourceTree = ""; }; + A2580EFC2A8E8CDC0010CEFA /* km */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = km; path = km.lproj/Localizable.strings; sourceTree = ""; }; + A2580EFD2A8E8CDC0010CEFA /* ne */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ne; path = ne.lproj/Localizable.strings; sourceTree = ""; }; + A2580EFE2A8E8CDC0010CEFA /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/Localizable.strings; sourceTree = ""; }; + A2580EFF2A8E8CDC0010CEFA /* ur */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ur; path = ur.lproj/Localizable.strings; sourceTree = ""; }; + A2580F002A8E8CDC0010CEFA /* fil */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fil; path = fil.lproj/Localizable.strings; sourceTree = ""; }; + A2580F012A8E8CDC0010CEFA /* hy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hy; path = hy.lproj/Localizable.strings; sourceTree = ""; }; + A2580F022A8E8CDC0010CEFA /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; + A2580F032A8E8CDD0010CEFA /* my */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = my; path = my.lproj/Localizable.strings; sourceTree = ""; }; + A2580F042A8E8CDD0010CEFA /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; A26D262D2A1C41B1009838E0 /* OutlineLauncher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OutlineLauncher.app; sourceTree = BUILT_PRODUCTS_DIR; }; A26D26382A1C41B4009838E0 /* OutlineLauncher.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OutlineLauncher.entitlements; sourceTree = ""; }; A271D42C2A708240009981B2 /* AppDelegate+Outline.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "AppDelegate+Outline.m"; sourceTree = ""; }; @@ -280,6 +347,7 @@ 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( + A2580EC22A8E8CDA0010CEFA /* Localizable.strings */, FC55AB411F4F960A0056F12C /* VpnExtension-Info.plist */, 0207DA571B56EA530066E2B4 /* Assets.xcassets */, 3047A50E1AB8057F00498E2A /* config */, @@ -495,12 +563,77 @@ }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Outline" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 1; knownRegions = ( - English, en, Base, + ar, + cs, + ms, + lt, + kk, + ko, + sl, + ne, + is, + sq, + hy, + uk, + de, + sw, + si, + bn, + bs, + tr, + vi, + az, + et, + "pt-PT", + lv, + he, + hi, + mk, + ta, + pl, + fil, + my, + mr, + fa, + am, + lo, + km, + th, + sr, + ca, + "zh-Hant", + da, + "es-419", + "en-GB", + ro, + bg, + id, + hu, + ja, + es, + "pt-BR", + nl, + it, + ru, + hr, + fr, + el, + sk, + "sr-Latn", + ka, + sv, + af, + mn, + ur, + no, + nb, + "zh-Hans", + fi, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; packageReferences = ( @@ -546,6 +679,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + A2580F052A8E8CDD0010CEFA /* Localizable.strings in Resources */, 302D95F214D2391D003F00A1 /* MainViewController.xib in Resources */, 0207DA581B56EA530066E2B4 /* Assets.xcassets in Resources */, 6AFF5BF91D6E424B00AB3073 /* CDVLaunchScreen.storyboard in Resources */, @@ -640,6 +774,82 @@ }; /* End PBXTargetDependency section */ +/* Begin PBXVariantGroup section */ + A2580EC22A8E8CDA0010CEFA /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + A2580EC32A8E8CDA0010CEFA /* da */, + A2580EC42A8E8CDA0010CEFA /* es-419 */, + A2580EC52A8E8CDA0010CEFA /* zh-Hans */, + A2580EC62A8E8CDA0010CEFA /* et */, + A2580EC72A8E8CDA0010CEFA /* mn */, + A2580EC82A8E8CDA0010CEFA /* pl */, + A2580EC92A8E8CDA0010CEFA /* he */, + A2580ECA2A8E8CDA0010CEFA /* el */, + A2580ECB2A8E8CDA0010CEFA /* fi */, + A2580ECC2A8E8CDA0010CEFA /* sl */, + A2580ECD2A8E8CDA0010CEFA /* en */, + A2580ECE2A8E8CDA0010CEFA /* ka */, + A2580ECF2A8E8CDA0010CEFA /* it */, + A2580ED02A8E8CDB0010CEFA /* bs */, + A2580ED12A8E8CDB0010CEFA /* de */, + A2580ED22A8E8CDB0010CEFA /* no */, + A2580ED32A8E8CDB0010CEFA /* sr-Latn */, + A2580ED42A8E8CDB0010CEFA /* sq */, + A2580ED52A8E8CDB0010CEFA /* tr */, + A2580ED62A8E8CDB0010CEFA /* vi */, + A2580ED72A8E8CDB0010CEFA /* en-GB */, + A2580ED82A8E8CDB0010CEFA /* th */, + A2580ED92A8E8CDB0010CEFA /* hi */, + A2580EDA2A8E8CDB0010CEFA /* is */, + A2580EDB2A8E8CDB0010CEFA /* ar */, + A2580EDC2A8E8CDB0010CEFA /* fr */, + A2580EDD2A8E8CDB0010CEFA /* pt-PT */, + A2580EDE2A8E8CDB0010CEFA /* ru */, + A2580EDF2A8E8CDB0010CEFA /* sw */, + A2580EE02A8E8CDB0010CEFA /* uk */, + A2580EE12A8E8CDB0010CEFA /* hr */, + A2580EE22A8E8CDB0010CEFA /* sk */, + A2580EE32A8E8CDB0010CEFA /* sr */, + A2580EE42A8E8CDB0010CEFA /* ca */, + A2580EE52A8E8CDB0010CEFA /* cs */, + A2580EE62A8E8CDB0010CEFA /* az */, + A2580EE72A8E8CDB0010CEFA /* ro */, + A2580EE82A8E8CDB0010CEFA /* ja */, + A2580EE92A8E8CDB0010CEFA /* lt */, + A2580EEA2A8E8CDC0010CEFA /* mk */, + A2580EEB2A8E8CDC0010CEFA /* hu */, + A2580EEC2A8E8CDC0010CEFA /* id */, + A2580EED2A8E8CDC0010CEFA /* zh-Hant */, + A2580EEE2A8E8CDC0010CEFA /* mr */, + A2580EEF2A8E8CDC0010CEFA /* ms */, + A2580EF02A8E8CDC0010CEFA /* es */, + A2580EF12A8E8CDC0010CEFA /* si */, + A2580EF22A8E8CDC0010CEFA /* bg */, + A2580EF32A8E8CDC0010CEFA /* lv */, + A2580EF42A8E8CDC0010CEFA /* lo */, + A2580EF52A8E8CDC0010CEFA /* ta */, + A2580EF62A8E8CDC0010CEFA /* am */, + A2580EF72A8E8CDC0010CEFA /* bn */, + A2580EF82A8E8CDC0010CEFA /* sv */, + A2580EF92A8E8CDC0010CEFA /* pt-BR */, + A2580EFA2A8E8CDC0010CEFA /* fa */, + A2580EFB2A8E8CDC0010CEFA /* af */, + A2580EFC2A8E8CDC0010CEFA /* km */, + A2580EFD2A8E8CDC0010CEFA /* ne */, + A2580EFE2A8E8CDC0010CEFA /* kk */, + A2580EFF2A8E8CDC0010CEFA /* ur */, + A2580F002A8E8CDC0010CEFA /* fil */, + A2580F012A8E8CDC0010CEFA /* hy */, + A2580F022A8E8CDC0010CEFA /* nl */, + A2580F032A8E8CDD0010CEFA /* my */, + A2580F042A8E8CDD0010CEFA /* ko */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + /* Begin XCBuildConfiguration section */ 1D6058940D05DD3E006BFB54 /* Debug */ = { isa = XCBuildConfiguration; diff --git a/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist b/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist index 22020f35c0f..b2d8a53155f 100644 --- a/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist +++ b/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist @@ -2,12 +2,8 @@ - CFBundleShortVersionString - 0.0.0-debug - CFBundleVersion - 0 CFBundleDevelopmentRegion - English + $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName Outline CFBundleExecutable @@ -24,6 +20,8 @@ ${PRODUCT_NAME} CFBundlePackageType APPL + CFBundleShortVersionString + 0.0.0-debug CFBundleSignature ???? CFBundleURLTypes @@ -36,10 +34,12 @@ - LSRequiresIPhoneOS - + CFBundleVersion + 0 ITSAppUsesNonExemptEncryption + LSRequiresIPhoneOS + LSUIElement NSAppTransportSecurity diff --git a/src/cordova/apple/xcode/ios/Outline/VpnExtension-Info.plist b/src/cordova/apple/xcode/ios/Outline/VpnExtension-Info.plist index 5d3ca566bba..e4e1e2a439a 100644 --- a/src/cordova/apple/xcode/ios/Outline/VpnExtension-Info.plist +++ b/src/cordova/apple/xcode/ios/Outline/VpnExtension-Info.plist @@ -2,16 +2,10 @@ - CFBundleShortVersionString - 0.0.0-debug - CFBundleVersion - 0 CFBundleDevelopmentRegion - en + $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName VpnExtension - ITSAppUsesNonExemptEncryption - CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -22,6 +16,12 @@ $(PRODUCT_NAME) CFBundlePackageType XPC! + CFBundleShortVersionString + 0.0.0-debug + CFBundleVersion + 0 + ITSAppUsesNonExemptEncryption + NSExtension NSExtensionPointIdentifier From a47557faeb0f63e94a764eece21bb039a8b6f666 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Thu, 17 Aug 2023 13:23:47 -0400 Subject: [PATCH 14/15] Use localized strings in the menu bar. --- .../StatusItemController.swift | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift index 90308f96af0..14834c78428 100644 --- a/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift @@ -29,12 +29,19 @@ static let statusDisconnected = getImage(name: "status_bar_button_image") } - // TODO: Internationalize these user-facing strings. private enum MenuTitle { - static let open = "Open" - static let quit = "Quit" - static let statusConnected = "Connected" - static let statusDisconnected = "Disconnected" + static let open = NSLocalizedString( + "tray_open_window", + comment: "Tray menu entry to show the application window.") + static let quit = NSLocalizedString( + "quit", + comment: "Tray menu entry to quit the application.") + static let statusConnected = NSLocalizedString( + "connected_server_state", + comment: "Tray menu entry indicating a server is currently connected and in use.") + static let statusDisconnected = NSLocalizedString( + "disconnected_server_state", + comment: "Tray menu entry indicating no server is currently connected.") } override init() { From a11637a620d869b1bfbd296ca4b16e996926bfd1 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Thu, 17 Aug 2023 14:29:40 -0400 Subject: [PATCH 15/15] Move localized strings into the Swift package, where they are used. --- .../apple/OutlineAppleLib/Package.swift | 1 + .../Strings}/af.lproj/Localizable.strings | 0 .../Strings}/am.lproj/Localizable.strings | 0 .../Strings}/ar.lproj/Localizable.strings | 0 .../Strings}/az.lproj/Localizable.strings | 0 .../Strings}/bg.lproj/Localizable.strings | 0 .../Strings}/bn.lproj/Localizable.strings | 0 .../Strings}/bs.lproj/Localizable.strings | 0 .../Strings}/ca.lproj/Localizable.strings | 0 .../Strings}/cs.lproj/Localizable.strings | 0 .../Strings}/da.lproj/Localizable.strings | 0 .../Strings}/de.lproj/Localizable.strings | 0 .../Strings}/el.lproj/Localizable.strings | 0 .../Strings}/en-GB.lproj/Localizable.strings | 0 .../Strings}/en.lproj/Localizable.strings | 0 .../Strings}/es-419.lproj/Localizable.strings | 0 .../Strings}/es.lproj/Localizable.strings | 0 .../Strings}/et.lproj/Localizable.strings | 0 .../Strings}/fa.lproj/Localizable.strings | 0 .../Strings}/fi.lproj/Localizable.strings | 0 .../Strings}/fil.lproj/Localizable.strings | 0 .../Strings}/fr.lproj/Localizable.strings | 0 .../Strings}/he.lproj/Localizable.strings | 0 .../Strings}/hi.lproj/Localizable.strings | 0 .../Strings}/hr.lproj/Localizable.strings | 0 .../Strings}/hu.lproj/Localizable.strings | 0 .../Strings}/hy.lproj/Localizable.strings | 0 .../Strings}/id.lproj/Localizable.strings | 0 .../Strings}/is.lproj/Localizable.strings | 0 .../Strings}/it.lproj/Localizable.strings | 0 .../Strings}/ja.lproj/Localizable.strings | 0 .../Strings}/ka.lproj/Localizable.strings | 0 .../Strings}/kk.lproj/Localizable.strings | 0 .../Strings}/km.lproj/Localizable.strings | 0 .../Strings}/ko.lproj/Localizable.strings | 0 .../Strings}/lo.lproj/Localizable.strings | 0 .../Strings}/lt.lproj/Localizable.strings | 0 .../Strings}/lv.lproj/Localizable.strings | 0 .../Strings}/mk.lproj/Localizable.strings | 0 .../Strings}/mn.lproj/Localizable.strings | 0 .../Strings}/mr.lproj/Localizable.strings | 0 .../Strings}/ms.lproj/Localizable.strings | 0 .../Strings}/my.lproj/Localizable.strings | 0 .../Strings}/ne.lproj/Localizable.strings | 0 .../Strings}/nl.lproj/Localizable.strings | 0 .../Strings}/no.lproj/Localizable.strings | 0 .../Strings}/pl.lproj/Localizable.strings | 0 .../Strings}/pt-BR.lproj/Localizable.strings | 0 .../Strings}/pt-PT.lproj/Localizable.strings | 0 .../Strings}/ro.lproj/Localizable.strings | 0 .../Strings}/ru.lproj/Localizable.strings | 0 .../Strings}/si.lproj/Localizable.strings | 0 .../Strings}/sk.lproj/Localizable.strings | 0 .../Strings}/sl.lproj/Localizable.strings | 0 .../Strings}/sq.lproj/Localizable.strings | 0 .../sr-Latn.lproj/Localizable.strings | 0 .../Strings}/sr.lproj/Localizable.strings | 0 .../Strings}/sv.lproj/Localizable.strings | 0 .../Strings}/sw.lproj/Localizable.strings | 0 .../Strings}/ta.lproj/Localizable.strings | 0 .../Strings}/th.lproj/Localizable.strings | 0 .../Strings}/tr.lproj/Localizable.strings | 0 .../Strings}/uk.lproj/Localizable.strings | 0 .../Strings}/ur.lproj/Localizable.strings | 0 .../Strings}/vi.lproj/Localizable.strings | 0 .../zh-Hans.lproj/Localizable.strings | 0 .../zh-Hant.lproj/Localizable.strings | 0 .../StatusItemController.swift | 4 + src/cordova/apple/import_messages.mjs | 2 +- .../ios/Outline.xcodeproj/project.pbxproj | 211 ------------------ .../xcode/ios/Outline/Outline-Info.plist | 2 + 71 files changed, 8 insertions(+), 212 deletions(-) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/af.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/am.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/ar.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/az.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/bg.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/bn.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/bs.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/ca.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/cs.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/da.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/de.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/el.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/en-GB.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/en.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/es-419.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/es.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/et.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/fa.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/fi.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/fil.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/fr.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/he.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/hi.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/hr.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/hu.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/hy.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/id.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/is.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/it.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/ja.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/ka.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/kk.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/km.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/ko.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/lo.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/lt.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/lv.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/mk.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/mn.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/mr.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/ms.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/my.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/ne.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/nl.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/no.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/pl.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/pt-BR.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/pt-PT.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/ro.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/ru.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/si.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/sk.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/sl.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/sq.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/sr-Latn.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/sr.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/sv.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/sw.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/ta.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/th.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/tr.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/uk.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/ur.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/vi.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/zh-Hans.lproj/Localizable.strings (100%) rename src/cordova/apple/{xcode/ios/Outline/Resources => OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings}/zh-Hant.lproj/Localizable.strings (100%) diff --git a/src/cordova/apple/OutlineAppleLib/Package.swift b/src/cordova/apple/OutlineAppleLib/Package.swift index 0219c673d4b..fbb04078cbc 100644 --- a/src/cordova/apple/OutlineAppleLib/Package.swift +++ b/src/cordova/apple/OutlineAppleLib/Package.swift @@ -5,6 +5,7 @@ import PackageDescription let package = Package( name: "OutlineAppleLib", + defaultLocalization: "en", products: [ .library( name: "OutlineAppleLib", diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/af.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/af.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/af.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/af.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/am.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/am.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/am.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/am.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ar.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ar.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/ar.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ar.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/az.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/az.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/az.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/az.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/bg.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/bg.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/bg.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/bg.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/bn.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/bn.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/bn.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/bn.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/bs.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/bs.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/bs.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/bs.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ca.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ca.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/ca.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ca.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/cs.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/cs.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/cs.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/cs.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/da.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/da.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/da.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/da.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/de.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/de.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/de.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/de.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/el.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/el.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/el.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/el.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/en-GB.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/en-GB.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/en-GB.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/en-GB.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/en.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/en.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/en.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/en.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/es-419.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/es-419.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/es-419.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/es-419.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/es.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/es.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/es.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/es.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/et.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/et.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/et.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/et.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/fa.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/fa.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/fa.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/fa.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/fi.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/fi.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/fi.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/fi.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/fil.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/fil.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/fil.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/fil.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/fr.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/fr.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/fr.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/fr.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/he.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/he.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/he.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/he.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/hi.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/hi.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/hi.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/hi.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/hr.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/hr.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/hr.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/hr.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/hu.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/hu.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/hu.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/hu.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/hy.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/hy.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/hy.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/hy.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/id.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/id.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/id.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/id.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/is.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/is.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/is.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/is.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/it.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/it.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/it.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/it.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ja.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ja.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/ja.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ja.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ka.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ka.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/ka.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ka.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/kk.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/kk.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/kk.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/kk.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/km.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/km.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/km.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/km.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ko.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ko.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/ko.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ko.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/lo.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/lo.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/lo.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/lo.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/lt.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/lt.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/lt.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/lt.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/lv.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/lv.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/lv.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/lv.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/mk.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/mk.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/mk.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/mk.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/mn.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/mn.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/mn.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/mn.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/mr.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/mr.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/mr.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/mr.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ms.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ms.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/ms.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ms.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/my.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/my.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/my.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/my.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ne.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ne.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/ne.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ne.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/nl.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/nl.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/nl.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/nl.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/no.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/no.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/no.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/no.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/pl.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/pl.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/pl.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/pl.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/pt-BR.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/pt-BR.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/pt-BR.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/pt-BR.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/pt-PT.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/pt-PT.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/pt-PT.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/pt-PT.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ro.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ro.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/ro.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ro.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ru.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ru.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/ru.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ru.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/si.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/si.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/si.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/si.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sk.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sk.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/sk.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sk.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sl.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sl.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/sl.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sl.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sq.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sq.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/sq.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sq.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sr-Latn.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sr-Latn.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/sr-Latn.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sr-Latn.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sr.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sr.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/sr.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sr.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sv.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sv.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/sv.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sv.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/sw.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sw.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/sw.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/sw.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ta.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ta.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/ta.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ta.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/th.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/th.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/th.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/th.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/tr.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/tr.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/tr.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/tr.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/uk.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/uk.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/uk.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/uk.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/ur.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ur.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/ur.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/ur.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/vi.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/vi.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/vi.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/vi.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/zh-Hans.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/zh-Hans.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/zh-Hans.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/zh-Hans.lproj/Localizable.strings diff --git a/src/cordova/apple/xcode/ios/Outline/Resources/zh-Hant.lproj/Localizable.strings b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/zh-Hant.lproj/Localizable.strings similarity index 100% rename from src/cordova/apple/xcode/ios/Outline/Resources/zh-Hant.lproj/Localizable.strings rename to src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/Resources/Strings/zh-Hant.lproj/Localizable.strings diff --git a/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift index 14834c78428..e053c3f3c7d 100644 --- a/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift +++ b/src/cordova/apple/OutlineAppleLib/Sources/OutlineAppKitBridge/StatusItemController.swift @@ -32,15 +32,19 @@ private enum MenuTitle { static let open = NSLocalizedString( "tray_open_window", + bundle: .module, comment: "Tray menu entry to show the application window.") static let quit = NSLocalizedString( "quit", + bundle: .module, comment: "Tray menu entry to quit the application.") static let statusConnected = NSLocalizedString( "connected_server_state", + bundle: .module, comment: "Tray menu entry indicating a server is currently connected and in use.") static let statusDisconnected = NSLocalizedString( "disconnected_server_state", + bundle: .module, comment: "Tray menu entry indicating no server is currently connected.") } diff --git a/src/cordova/apple/import_messages.mjs b/src/cordova/apple/import_messages.mjs index c1dd0f1a200..dcabcff4e6e 100644 --- a/src/cordova/apple/import_messages.mjs +++ b/src/cordova/apple/import_messages.mjs @@ -15,7 +15,7 @@ import path from 'path'; import I18N from 'i18n-strings-files'; -const STRINGS_DIR = ['src', 'cordova', 'apple', 'xcode', 'ios', 'Outline', 'Resources']; +const STRINGS_DIR = ['src', 'cordova', 'apple', 'OutlineAppleLib', 'Sources', 'OutlineAppKitBridge', 'Resources', 'Strings']; const STRINGS_FILENAME = 'Localizable.strings'; function getNativeLocale(locale) { diff --git a/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj b/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj index 9a832f8e289..6ac1e5cf3eb 100755 --- a/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj +++ b/src/cordova/apple/xcode/ios/Outline.xcodeproj/project.pbxproj @@ -21,7 +21,6 @@ 52E783062A5880CF00355E64 /* PacketTunnelProvider in Frameworks */ = {isa = PBXBuildFile; productRef = 52E783052A5880CF00355E64 /* PacketTunnelProvider */; }; 5F7F90AE0E924FD7B065C415 /* CDVStatusBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 0394302BA6114B2AB648D4FF /* CDVStatusBar.m */; }; 6AFF5BF91D6E424B00AB3073 /* CDVLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */; }; - A2580F052A8E8CDD0010CEFA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A2580EC22A8E8CDA0010CEFA /* Localizable.strings */; }; A271D4202A7069D8009981B2 /* OutlineLauncher in Frameworks */ = {isa = PBXBuildFile; productRef = A271D41F2A7069D8009981B2 /* OutlineLauncher */; }; A271D4222A706CB9009981B2 /* OutlineAppKitBridge in Frameworks */ = {isa = PBXBuildFile; productRef = A271D4212A706CB9009981B2 /* OutlineAppKitBridge */; }; A271D42D2A708240009981B2 /* AppDelegate+Outline.m in Sources */ = {isa = PBXBuildFile; fileRef = A271D42C2A708240009981B2 /* AppDelegate+Outline.m */; }; @@ -162,72 +161,6 @@ 91E45572BB494E9299D2DD41 /* CDVClipboard.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVClipboard.m; path = "cordova-plugin-clipboard/CDVClipboard.m"; sourceTree = ""; }; 936C2951B7544BC8A20B6746 /* CDVClipboard.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVClipboard.h; path = "cordova-plugin-clipboard/CDVClipboard.h"; sourceTree = ""; }; 941052A220F54953928FF2E2 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; - A2580EC32A8E8CDA0010CEFA /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = ""; }; - A2580EC42A8E8CDA0010CEFA /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = ""; }; - A2580EC52A8E8CDA0010CEFA /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; - A2580EC62A8E8CDA0010CEFA /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Localizable.strings; sourceTree = ""; }; - A2580EC72A8E8CDA0010CEFA /* mn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mn; path = mn.lproj/Localizable.strings; sourceTree = ""; }; - A2580EC82A8E8CDA0010CEFA /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = ""; }; - A2580EC92A8E8CDA0010CEFA /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Localizable.strings; sourceTree = ""; }; - A2580ECA2A8E8CDA0010CEFA /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Localizable.strings; sourceTree = ""; }; - A2580ECB2A8E8CDA0010CEFA /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = ""; }; - A2580ECC2A8E8CDA0010CEFA /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/Localizable.strings; sourceTree = ""; }; - A2580ECD2A8E8CDA0010CEFA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; - A2580ECE2A8E8CDA0010CEFA /* ka */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ka; path = ka.lproj/Localizable.strings; sourceTree = ""; }; - A2580ECF2A8E8CDA0010CEFA /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; - A2580ED02A8E8CDB0010CEFA /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/Localizable.strings; sourceTree = ""; }; - A2580ED12A8E8CDB0010CEFA /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; - A2580ED22A8E8CDB0010CEFA /* no */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = no; path = no.lproj/Localizable.strings; sourceTree = ""; }; - A2580ED32A8E8CDB0010CEFA /* sr-Latn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sr-Latn"; path = "sr-Latn.lproj/Localizable.strings"; sourceTree = ""; }; - A2580ED42A8E8CDB0010CEFA /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = sq.lproj/Localizable.strings; sourceTree = ""; }; - A2580ED52A8E8CDB0010CEFA /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; - A2580ED62A8E8CDB0010CEFA /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = ""; }; - A2580ED72A8E8CDB0010CEFA /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = ""; }; - A2580ED82A8E8CDB0010CEFA /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/Localizable.strings; sourceTree = ""; }; - A2580ED92A8E8CDB0010CEFA /* hi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hi; path = hi.lproj/Localizable.strings; sourceTree = ""; }; - A2580EDA2A8E8CDB0010CEFA /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/Localizable.strings; sourceTree = ""; }; - A2580EDB2A8E8CDB0010CEFA /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = ""; }; - A2580EDC2A8E8CDB0010CEFA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; - A2580EDD2A8E8CDB0010CEFA /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = ""; }; - A2580EDE2A8E8CDB0010CEFA /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; - A2580EDF2A8E8CDB0010CEFA /* sw */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sw; path = sw.lproj/Localizable.strings; sourceTree = ""; }; - A2580EE02A8E8CDB0010CEFA /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = ""; }; - A2580EE12A8E8CDB0010CEFA /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Localizable.strings; sourceTree = ""; }; - A2580EE22A8E8CDB0010CEFA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Localizable.strings; sourceTree = ""; }; - A2580EE32A8E8CDB0010CEFA /* sr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sr; path = sr.lproj/Localizable.strings; sourceTree = ""; }; - A2580EE42A8E8CDB0010CEFA /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = ""; }; - A2580EE52A8E8CDB0010CEFA /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; - A2580EE62A8E8CDB0010CEFA /* az */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = az; path = az.lproj/Localizable.strings; sourceTree = ""; }; - A2580EE72A8E8CDB0010CEFA /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = ""; }; - A2580EE82A8E8CDB0010CEFA /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = ""; }; - A2580EE92A8E8CDB0010CEFA /* lt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lt; path = lt.lproj/Localizable.strings; sourceTree = ""; }; - A2580EEA2A8E8CDC0010CEFA /* mk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mk; path = mk.lproj/Localizable.strings; sourceTree = ""; }; - A2580EEB2A8E8CDC0010CEFA /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = ""; }; - A2580EEC2A8E8CDC0010CEFA /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/Localizable.strings; sourceTree = ""; }; - A2580EED2A8E8CDC0010CEFA /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = ""; }; - A2580EEE2A8E8CDC0010CEFA /* mr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mr; path = mr.lproj/Localizable.strings; sourceTree = ""; }; - A2580EEF2A8E8CDC0010CEFA /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/Localizable.strings; sourceTree = ""; }; - A2580EF02A8E8CDC0010CEFA /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; - A2580EF12A8E8CDC0010CEFA /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/Localizable.strings; sourceTree = ""; }; - A2580EF22A8E8CDC0010CEFA /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/Localizable.strings; sourceTree = ""; }; - A2580EF32A8E8CDC0010CEFA /* lv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lv; path = lv.lproj/Localizable.strings; sourceTree = ""; }; - A2580EF42A8E8CDC0010CEFA /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/Localizable.strings; sourceTree = ""; }; - A2580EF52A8E8CDC0010CEFA /* ta */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ta; path = ta.lproj/Localizable.strings; sourceTree = ""; }; - A2580EF62A8E8CDC0010CEFA /* am */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = am; path = am.lproj/Localizable.strings; sourceTree = ""; }; - A2580EF72A8E8CDC0010CEFA /* bn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bn; path = bn.lproj/Localizable.strings; sourceTree = ""; }; - A2580EF82A8E8CDC0010CEFA /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; - A2580EF92A8E8CDC0010CEFA /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = ""; }; - A2580EFA2A8E8CDC0010CEFA /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = ""; }; - A2580EFB2A8E8CDC0010CEFA /* af */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = af; path = af.lproj/Localizable.strings; sourceTree = ""; }; - A2580EFC2A8E8CDC0010CEFA /* km */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = km; path = km.lproj/Localizable.strings; sourceTree = ""; }; - A2580EFD2A8E8CDC0010CEFA /* ne */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ne; path = ne.lproj/Localizable.strings; sourceTree = ""; }; - A2580EFE2A8E8CDC0010CEFA /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/Localizable.strings; sourceTree = ""; }; - A2580EFF2A8E8CDC0010CEFA /* ur */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ur; path = ur.lproj/Localizable.strings; sourceTree = ""; }; - A2580F002A8E8CDC0010CEFA /* fil */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fil; path = fil.lproj/Localizable.strings; sourceTree = ""; }; - A2580F012A8E8CDC0010CEFA /* hy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hy; path = hy.lproj/Localizable.strings; sourceTree = ""; }; - A2580F022A8E8CDC0010CEFA /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; - A2580F032A8E8CDD0010CEFA /* my */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = my; path = my.lproj/Localizable.strings; sourceTree = ""; }; - A2580F042A8E8CDD0010CEFA /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; A26D262D2A1C41B1009838E0 /* OutlineLauncher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OutlineLauncher.app; sourceTree = BUILT_PRODUCTS_DIR; }; A26D26382A1C41B4009838E0 /* OutlineLauncher.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OutlineLauncher.entitlements; sourceTree = ""; }; A271D42C2A708240009981B2 /* AppDelegate+Outline.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "AppDelegate+Outline.m"; sourceTree = ""; }; @@ -347,7 +280,6 @@ 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( - A2580EC22A8E8CDA0010CEFA /* Localizable.strings */, FC55AB411F4F960A0056F12C /* VpnExtension-Info.plist */, 0207DA571B56EA530066E2B4 /* Assets.xcassets */, 3047A50E1AB8057F00498E2A /* config */, @@ -568,72 +500,6 @@ knownRegions = ( en, Base, - ar, - cs, - ms, - lt, - kk, - ko, - sl, - ne, - is, - sq, - hy, - uk, - de, - sw, - si, - bn, - bs, - tr, - vi, - az, - et, - "pt-PT", - lv, - he, - hi, - mk, - ta, - pl, - fil, - my, - mr, - fa, - am, - lo, - km, - th, - sr, - ca, - "zh-Hant", - da, - "es-419", - "en-GB", - ro, - bg, - id, - hu, - ja, - es, - "pt-BR", - nl, - it, - ru, - hr, - fr, - el, - sk, - "sr-Latn", - ka, - sv, - af, - mn, - ur, - no, - nb, - "zh-Hans", - fi, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; packageReferences = ( @@ -679,7 +545,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - A2580F052A8E8CDD0010CEFA /* Localizable.strings in Resources */, 302D95F214D2391D003F00A1 /* MainViewController.xib in Resources */, 0207DA581B56EA530066E2B4 /* Assets.xcassets in Resources */, 6AFF5BF91D6E424B00AB3073 /* CDVLaunchScreen.storyboard in Resources */, @@ -774,82 +639,6 @@ }; /* End PBXTargetDependency section */ -/* Begin PBXVariantGroup section */ - A2580EC22A8E8CDA0010CEFA /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - A2580EC32A8E8CDA0010CEFA /* da */, - A2580EC42A8E8CDA0010CEFA /* es-419 */, - A2580EC52A8E8CDA0010CEFA /* zh-Hans */, - A2580EC62A8E8CDA0010CEFA /* et */, - A2580EC72A8E8CDA0010CEFA /* mn */, - A2580EC82A8E8CDA0010CEFA /* pl */, - A2580EC92A8E8CDA0010CEFA /* he */, - A2580ECA2A8E8CDA0010CEFA /* el */, - A2580ECB2A8E8CDA0010CEFA /* fi */, - A2580ECC2A8E8CDA0010CEFA /* sl */, - A2580ECD2A8E8CDA0010CEFA /* en */, - A2580ECE2A8E8CDA0010CEFA /* ka */, - A2580ECF2A8E8CDA0010CEFA /* it */, - A2580ED02A8E8CDB0010CEFA /* bs */, - A2580ED12A8E8CDB0010CEFA /* de */, - A2580ED22A8E8CDB0010CEFA /* no */, - A2580ED32A8E8CDB0010CEFA /* sr-Latn */, - A2580ED42A8E8CDB0010CEFA /* sq */, - A2580ED52A8E8CDB0010CEFA /* tr */, - A2580ED62A8E8CDB0010CEFA /* vi */, - A2580ED72A8E8CDB0010CEFA /* en-GB */, - A2580ED82A8E8CDB0010CEFA /* th */, - A2580ED92A8E8CDB0010CEFA /* hi */, - A2580EDA2A8E8CDB0010CEFA /* is */, - A2580EDB2A8E8CDB0010CEFA /* ar */, - A2580EDC2A8E8CDB0010CEFA /* fr */, - A2580EDD2A8E8CDB0010CEFA /* pt-PT */, - A2580EDE2A8E8CDB0010CEFA /* ru */, - A2580EDF2A8E8CDB0010CEFA /* sw */, - A2580EE02A8E8CDB0010CEFA /* uk */, - A2580EE12A8E8CDB0010CEFA /* hr */, - A2580EE22A8E8CDB0010CEFA /* sk */, - A2580EE32A8E8CDB0010CEFA /* sr */, - A2580EE42A8E8CDB0010CEFA /* ca */, - A2580EE52A8E8CDB0010CEFA /* cs */, - A2580EE62A8E8CDB0010CEFA /* az */, - A2580EE72A8E8CDB0010CEFA /* ro */, - A2580EE82A8E8CDB0010CEFA /* ja */, - A2580EE92A8E8CDB0010CEFA /* lt */, - A2580EEA2A8E8CDC0010CEFA /* mk */, - A2580EEB2A8E8CDC0010CEFA /* hu */, - A2580EEC2A8E8CDC0010CEFA /* id */, - A2580EED2A8E8CDC0010CEFA /* zh-Hant */, - A2580EEE2A8E8CDC0010CEFA /* mr */, - A2580EEF2A8E8CDC0010CEFA /* ms */, - A2580EF02A8E8CDC0010CEFA /* es */, - A2580EF12A8E8CDC0010CEFA /* si */, - A2580EF22A8E8CDC0010CEFA /* bg */, - A2580EF32A8E8CDC0010CEFA /* lv */, - A2580EF42A8E8CDC0010CEFA /* lo */, - A2580EF52A8E8CDC0010CEFA /* ta */, - A2580EF62A8E8CDC0010CEFA /* am */, - A2580EF72A8E8CDC0010CEFA /* bn */, - A2580EF82A8E8CDC0010CEFA /* sv */, - A2580EF92A8E8CDC0010CEFA /* pt-BR */, - A2580EFA2A8E8CDC0010CEFA /* fa */, - A2580EFB2A8E8CDC0010CEFA /* af */, - A2580EFC2A8E8CDC0010CEFA /* km */, - A2580EFD2A8E8CDC0010CEFA /* ne */, - A2580EFE2A8E8CDC0010CEFA /* kk */, - A2580EFF2A8E8CDC0010CEFA /* ur */, - A2580F002A8E8CDC0010CEFA /* fil */, - A2580F012A8E8CDC0010CEFA /* hy */, - A2580F022A8E8CDC0010CEFA /* nl */, - A2580F032A8E8CDD0010CEFA /* my */, - A2580F042A8E8CDD0010CEFA /* ko */, - ); - name = Localizable.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ 1D6058940D05DD3E006BFB54 /* Debug */ = { isa = XCBuildConfiguration; diff --git a/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist b/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist index b2d8a53155f..0ae48e9d842 100644 --- a/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist +++ b/src/cordova/apple/xcode/ios/Outline/Outline-Info.plist @@ -38,6 +38,8 @@ 0 ITSAppUsesNonExemptEncryption + CFBundleAllowMixedLocalizations + LSRequiresIPhoneOS LSUIElement