diff --git a/.gitignore b/.gitignore
index 4a858ff704..c9b2e3c887 100644
--- a/.gitignore
+++ b/.gitignore
@@ -107,4 +107,8 @@ artifacts
rust/cw-contracts/*/target
# cypress
-cypress/screenshots
\ No newline at end of file
+cypress/screenshots
+
+# multi-app
+/app-selector.js
+/app.config.js
diff --git a/app-selector.js b/app-selector.js
new file mode 100644
index 0000000000..4e3081fb3e
--- /dev/null
+++ b/app-selector.js
@@ -0,0 +1 @@
+require("./apps/teritori/index");
diff --git a/app.config.js b/app.config.js
index 4c15a00f6d..f16da0f3e5 100644
--- a/app.config.js
+++ b/app.config.js
@@ -1,79 +1 @@
-const config = {
- expo: {
- name: "Teritori",
- slug: "teritori",
- version: "1.0.3",
- orientation: "portrait",
- icon: "./assets/app-icon.png",
- owner: "teritori",
- userInterfaceStyle: "light",
- splash: {
- image: "./assets/splash.png",
- resizeMode: "contain",
- backgroundColor: "#000000",
- },
- updates: {
- fallbackToCacheTimeout: 0,
- },
- assetBundlePatterns: ["**/*"],
- ios: {
- supportsTablet: true,
- bundleIdentifier: "com.teritori",
- buildNumber: "5",
- infoPlist: {
- NSBluetoothAlwaysUsageDescription: "Used for Bluetooth communications",
- NSBluetoothPeripheralUsageDescription:
- "Used for Bluetooth communications",
- NSPhotoLibraryUsageDescription:
- "Access to your photo library is required for image upload functionality.",
- ITSAppUsesNonExemptEncryption: false,
- UIBackgroundModes: ["audio"],
- },
- },
- android: {
- package: "com.teritori",
- versionCode: "6",
- permissions: [
- "WAKE_LOCK",
- "BLUETOOTH",
- "BLUETOOTH_ADMIN",
- "BLUETOOTH_ADVERTISE",
- "BLUETOOTH_SCAN",
- "BLUETOOTH_CONNECT",
- "ACCESS_NETWORK_STATE",
- "CHANGE_NETWORK_STATE",
- "CHANGE_WIFI_STATE",
- "ACCESS_WIFI_STATE",
- "CHANGE_WIFI_MULTICAST_STATE",
- "NFC",
- ],
- },
- web: {
- bundler: "metro",
- favicon: "./assets/favicon.png",
- },
- extra: {
- eas: {
- projectId: "9ce165de-0199-478c-b3bd-8688e5ce03eb",
- },
- },
- plugins: [
- "expo-font",
- [
- "expo-document-picker",
- {
- iCloudContainerEnvironment: "Production",
- },
- ],
- [
- "react-native-vision-camera",
- {
- cameraPermissionText: "$(PRODUCT_NAME) needs access to your Camera.",
- enableCodeScanner: true,
- },
- ],
- ],
- },
-};
-
-export default config;
+module.exports = require("./apps/teritori/app.config.js");
diff --git a/apps/gno-dapp/App.tsx b/apps/gnotribe/App.tsx
similarity index 86%
rename from apps/gno-dapp/App.tsx
rename to apps/gnotribe/App.tsx
index dc629459ca..e146880d78 100644
--- a/apps/gno-dapp/App.tsx
+++ b/apps/gnotribe/App.tsx
@@ -1,3 +1,4 @@
+import logo from "@/assets/logos/gnotribe-toplogo.svg";
import { AppConfig } from "@/context/AppConfigProvider";
import AppRoot from "@/dapp-root/App";
@@ -8,6 +9,7 @@ const config: AppConfig = {
forceDAppsList: ["feed", "organizations"],
defaultNetworkId: "gno-test5",
homeScreen: "Feed",
+ logo,
};
export const App: React.FC = () => {
diff --git a/apps/gnotribe/app.config.js b/apps/gnotribe/app.config.js
new file mode 100644
index 0000000000..1fe0ed14b7
--- /dev/null
+++ b/apps/gnotribe/app.config.js
@@ -0,0 +1,77 @@
+module.exports = {
+ expo: {
+ name: "Gnotribe",
+ slug: "gnotribe",
+ version: "1.0.3",
+ orientation: "portrait",
+ icon: "./apps/gnotribe/icon.png",
+ owner: "gnotribe",
+ userInterfaceStyle: "light",
+ splash: {
+ image: "./assets/splash.png",
+ resizeMode: "contain",
+ backgroundColor: "#000000",
+ },
+ updates: {
+ fallbackToCacheTimeout: 0,
+ },
+ assetBundlePatterns: ["**/*"],
+ ios: {
+ supportsTablet: true,
+ bundleIdentifier: "com.teritori.gnotribe",
+ buildNumber: "5",
+ infoPlist: {
+ NSBluetoothAlwaysUsageDescription: "Used for Bluetooth communications",
+ NSBluetoothPeripheralUsageDescription:
+ "Used for Bluetooth communications",
+ NSPhotoLibraryUsageDescription:
+ "Access to your photo library is required for image upload functionality.",
+ ITSAppUsesNonExemptEncryption: false,
+ UIBackgroundModes: ["audio"],
+ },
+ },
+ android: {
+ package: "com.teritori.gnotribe",
+ versionCode: 6,
+ permissions: [
+ "WAKE_LOCK",
+ "BLUETOOTH",
+ "BLUETOOTH_ADMIN",
+ "BLUETOOTH_ADVERTISE",
+ "BLUETOOTH_SCAN",
+ "BLUETOOTH_CONNECT",
+ "ACCESS_NETWORK_STATE",
+ "CHANGE_NETWORK_STATE",
+ "CHANGE_WIFI_STATE",
+ "ACCESS_WIFI_STATE",
+ "CHANGE_WIFI_MULTICAST_STATE",
+ "NFC",
+ ],
+ },
+ web: {
+ bundler: "metro",
+ favicon: "./apps/gnotribe/icon.png",
+ },
+ extra: {
+ eas: {
+ projectId: "9ce165de-0199-478c-b3bd-8688e5ce03eb",
+ },
+ },
+ plugins: [
+ "expo-font",
+ [
+ "expo-document-picker",
+ {
+ iCloudContainerEnvironment: "Production",
+ },
+ ],
+ [
+ "react-native-vision-camera",
+ {
+ cameraPermissionText: "$(PRODUCT_NAME) needs access to your Camera.",
+ enableCodeScanner: true,
+ },
+ ],
+ ],
+ },
+};
diff --git a/apps/gnotribe/icon.png b/apps/gnotribe/icon.png
new file mode 100644
index 0000000000..315ce7a7ed
Binary files /dev/null and b/apps/gnotribe/icon.png differ
diff --git a/apps/gno-dapp/index.js b/apps/gnotribe/index.js
similarity index 100%
rename from apps/gno-dapp/index.js
rename to apps/gnotribe/index.js
diff --git a/apps/teritori-dapp/netlify.toml b/apps/gnotribe/netlify.toml
similarity index 53%
rename from apps/teritori-dapp/netlify.toml
rename to apps/gnotribe/netlify.toml
index 3ad63160b1..06ee85e43a 100644
--- a/apps/teritori-dapp/netlify.toml
+++ b/apps/gnotribe/netlify.toml
@@ -1,5 +1,5 @@
[build]
-command = 'npm i -g sharp-cli && npx expo-optimize && npx expo export -p web'
+command = 'npx tsx packages/scripts/switch-app gnotribe && npm i -g sharp-cli && npx expo-optimize && npx expo export -p web'
publish = '/dist'
[build.environment]
NODE_OPTIONS = "--max_old_space_size=4096"
diff --git a/apps/teritori-dapp/App.tsx b/apps/teritori/App.tsx
similarity index 100%
rename from apps/teritori-dapp/App.tsx
rename to apps/teritori/App.tsx
diff --git a/apps/teritori/app.config.js b/apps/teritori/app.config.js
new file mode 100644
index 0000000000..6538d9dc85
--- /dev/null
+++ b/apps/teritori/app.config.js
@@ -0,0 +1,77 @@
+module.exports = {
+ expo: {
+ name: "Teritori",
+ slug: "teritori",
+ version: "1.0.3",
+ orientation: "portrait",
+ icon: "./assets/app-icon.png",
+ owner: "teritori",
+ userInterfaceStyle: "light",
+ splash: {
+ image: "./assets/splash.png",
+ resizeMode: "contain",
+ backgroundColor: "#000000",
+ },
+ updates: {
+ fallbackToCacheTimeout: 0,
+ },
+ assetBundlePatterns: ["**/*"],
+ ios: {
+ supportsTablet: true,
+ bundleIdentifier: "com.teritori",
+ buildNumber: "5",
+ infoPlist: {
+ NSBluetoothAlwaysUsageDescription: "Used for Bluetooth communications",
+ NSBluetoothPeripheralUsageDescription:
+ "Used for Bluetooth communications",
+ NSPhotoLibraryUsageDescription:
+ "Access to your photo library is required for image upload functionality.",
+ ITSAppUsesNonExemptEncryption: false,
+ UIBackgroundModes: ["audio"],
+ },
+ },
+ android: {
+ package: "com.teritori",
+ versionCode: 6,
+ permissions: [
+ "WAKE_LOCK",
+ "BLUETOOTH",
+ "BLUETOOTH_ADMIN",
+ "BLUETOOTH_ADVERTISE",
+ "BLUETOOTH_SCAN",
+ "BLUETOOTH_CONNECT",
+ "ACCESS_NETWORK_STATE",
+ "CHANGE_NETWORK_STATE",
+ "CHANGE_WIFI_STATE",
+ "ACCESS_WIFI_STATE",
+ "CHANGE_WIFI_MULTICAST_STATE",
+ "NFC",
+ ],
+ },
+ web: {
+ bundler: "metro",
+ favicon: "./assets/favicon.png",
+ },
+ extra: {
+ eas: {
+ projectId: "9ce165de-0199-478c-b3bd-8688e5ce03eb",
+ },
+ },
+ plugins: [
+ "expo-font",
+ [
+ "expo-document-picker",
+ {
+ iCloudContainerEnvironment: "Production",
+ },
+ ],
+ [
+ "react-native-vision-camera",
+ {
+ cameraPermissionText: "$(PRODUCT_NAME) needs access to your Camera.",
+ enableCodeScanner: true,
+ },
+ ],
+ ],
+ },
+};
diff --git a/apps/teritori-dapp/index.js b/apps/teritori/index.js
similarity index 100%
rename from apps/teritori-dapp/index.js
rename to apps/teritori/index.js
diff --git a/apps/gno-dapp/netlify.toml b/apps/teritori/netlify.toml
similarity index 53%
rename from apps/gno-dapp/netlify.toml
rename to apps/teritori/netlify.toml
index 1736587b69..275f2cd157 100644
--- a/apps/gno-dapp/netlify.toml
+++ b/apps/teritori/netlify.toml
@@ -1,5 +1,5 @@
[build]
-command = 'sed -i "s/teritori-dapp/gno-dapp/" package.json && npm i -g sharp-cli && npx expo-optimize && npx expo export -p web'
+command = 'npx tsx packages/scripts/switch-app teritori && npm i -g sharp-cli && npx expo-optimize && npx expo export -p web'
publish = '/dist'
[build.environment]
NODE_OPTIONS = "--max_old_space_size=4096"
diff --git a/assets/logos/gnotribe-logo.svg b/assets/logos/gnotribe-logo.svg
new file mode 100644
index 0000000000..55844c121e
--- /dev/null
+++ b/assets/logos/gnotribe-logo.svg
@@ -0,0 +1,83 @@
+
diff --git a/assets/logos/gnotribe-toplogo.svg b/assets/logos/gnotribe-toplogo.svg
new file mode 100644
index 0000000000..acc8742ae4
--- /dev/null
+++ b/assets/logos/gnotribe-toplogo.svg
@@ -0,0 +1,470 @@
+
\ No newline at end of file
diff --git a/package.json b/package.json
index e8ed206254..ed67ee40a5 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "teritori-dapp",
"version": "1.0.0",
- "main": "apps/teritori-dapp/index.js",
+ "main": "app-selector.js",
"scripts": {
"start": "expo start",
"android": "expo run:android",
diff --git a/packages/components/navigation/components/TopLogo.tsx b/packages/components/navigation/components/TopLogo.tsx
index 31c04283b3..c8720871ee 100644
--- a/packages/components/navigation/components/TopLogo.tsx
+++ b/packages/components/navigation/components/TopLogo.tsx
@@ -1,21 +1,22 @@
import React from "react";
import { View, TouchableOpacity, ViewStyle } from "react-native";
-import logoTopVersionSVG from "../../../../assets/logos/logo-hexagon-version-alpha.svg";
-import { layout } from "../../../utils/style/layout";
-import { SVG } from "../../SVG";
-
+import logoTopVersionSVG from "@/assets/logos/logo-hexagon-version-alpha.svg";
+import { SVG } from "@/components/SVG";
import { useAppConfig } from "@/context/AppConfigProvider";
import { useAppNavigation } from "@/hooks/navigation/useAppNavigation";
+import { layout } from "@/utils/style/layout";
export const TopLogo = () => {
const navigation = useAppNavigation();
- const { homeScreen } = useAppConfig();
+ const { homeScreen, logo: configLogo } = useAppConfig();
- const logo = ;
+ const logoSource = configLogo || logoTopVersionSVG;
+ const logo = ;
const style: ViewStyle = {
- marginHorizontal: layout.spacing_x0_5,
+ marginHorizontal: layout.spacing_x0_25,
+ overflow: "hidden",
};
const content =
diff --git a/packages/context/AppConfigProvider.tsx b/packages/context/AppConfigProvider.tsx
index 06b6f12e94..0ec5a66b2a 100644
--- a/packages/context/AppConfigProvider.tsx
+++ b/packages/context/AppConfigProvider.tsx
@@ -1,4 +1,5 @@
import { createContext, useContext } from "react";
+import { SvgProps } from "react-native-svg";
import { RootStackParamList } from "@/utils/navigation";
@@ -9,6 +10,7 @@ export interface AppConfig {
forceDAppsList?: string[];
defaultNetworkId: string;
homeScreen: keyof RootStackParamList;
+ logo?: React.FC;
}
const defaultValue: AppConfig = {
defaultNetworkId: "teritori",
diff --git a/packages/scripts/app-build/fixGitignore.ts b/packages/scripts/app-build/fixGitignore.ts
index 115ce5e1b9..183edbcfd7 100644
--- a/packages/scripts/app-build/fixGitignore.ts
+++ b/packages/scripts/app-build/fixGitignore.ts
@@ -6,6 +6,8 @@ const TO_REMOVE_ITEMS = [
"/weshd/ios/Frameworks/",
"/weshd/android/libs/",
"/ios",
+ "/app-selector.js",
+ "/app.config.js",
];
fs.readFile(FILE_PATH, "utf8", (err, data) => {
diff --git a/packages/scripts/switch-app.ts b/packages/scripts/switch-app.ts
new file mode 100644
index 0000000000..4c8cf719bc
--- /dev/null
+++ b/packages/scripts/switch-app.ts
@@ -0,0 +1,35 @@
+import { program } from "commander";
+import fs from "fs";
+import fsp from "fs/promises";
+import path from "path";
+
+const main = async () => {
+ const [appName] = program.argument("").parse().args;
+
+ const rootPath = path.join(__dirname, "..", "..");
+ const appsPath = path.join(rootPath, "apps");
+ const appPath = path.join(appsPath, appName);
+ const exists = fs.existsSync(appPath);
+ if (!exists) {
+ let apps: string[] = [];
+ try {
+ apps = await fsp.readdir(appsPath, {});
+ apps = apps.filter((app) => ![".DS_Store"].includes(app));
+ } catch {}
+ console.error(
+ `ERROR: App ${JSON.stringify(appName)} does not exist, must be one of ${apps.map((app) => JSON.stringify(app)).join(", ")}`,
+ );
+ process.exit(1);
+ }
+
+ const appSelectorPath = path.join(rootPath, "app-selector.js");
+ await fsp.writeFile(appSelectorPath, `require("./apps/${appName}/index");\n`);
+
+ const appConfigPath = path.join(rootPath, "app.config.js");
+ await fsp.writeFile(
+ appConfigPath,
+ `module.exports = require("./apps/${appName}/app.config.js");\n`,
+ );
+};
+
+main();