diff --git a/install.zsh b/install.zsh index 58cdca6..48ed4d6 100755 --- a/install.zsh +++ b/install.zsh @@ -1,5 +1,23 @@ #!/bin/zsh +# Sed compatibility wrapper +function sediment() { + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "$@" + else + sed -i "$@" + fi +} + + +# Patch compatibility wrapper +function patchment() { + # -f : Force. Do not ask questions. (Standard in GNU and BSD patch) + # -N : Ignore patches that seem to be reversed or already applied (Forward) + # But we control these flags in the caller. + patch "$@" +} + function at-repos-env() { APP_PASSWORD=xxx host=syu.is @@ -102,26 +120,23 @@ function at-repos-social-app-avatar-write() { did_admin=did:plc:6qyecktefllvenje24fcxnie dt=$d/repos/social-app/src cd $dt - grep -R syu.is .|cut -d : -f 1|sort -u|xargs sed -i "s/syu.is/${host}/g" - grep -R web.syu.is .|cut -d : -f 1|sort -u|xargs sed -i "s/web.syu.is/web.${host}/g" + grep -R syu.is .|cut -d : -f 1|sort -u|xargs sediment "s/syu.is/${host}/g" + grep -R web.syu.is .|cut -d : -f 1|sort -u|xargs sediment "s/web.syu.is/web.${host}/g" f=$dt/lib/constants.ts - sed -i "s#export const BSKY_SERVICE = 'https://bsky.social'#export const BSKY_SERVICE = 'https://${host}'#g" $f - sed -i "s#export const BSKY_SERVICE_DID = 'did:web:bsky.social'#export const BSKY_SERVICE_DID = 'did:web:${host}'#g" $f - sed -i "s#export const PUBLIC_BSKY_SERVICE = 'https://public.api.bsky.app'#export const PUBLIC_BSKY_SERVICE = 'https://bsky.${host}'#g" $f - sed -i "s#export const PUBLIC_APPVIEW = 'https://api.bsky.app'#export const PUBLIC_APPVIEW = 'https://bsky.${host}'#g" $f - sed -i "s#export const PUBLIC_APPVIEW_DID = 'did:web:api.bsky.app'#export const PUBLIC_APPVIEW_DID = 'did:web:bsky.${host}'#g" $f - - f=$dt/view/icons/Logotype.tsx - o=$d/icons/Logotype.tsx - cp -rf $o $f + sediment "s#export const BSKY_SERVICE = 'https://bsky.social'#export const BSKY_SERVICE = 'https://${host}'#g" $f + sediment "s#export const BSKY_SERVICE_DID = 'did:web:bsky.social'#export const BSKY_SERVICE_DID = 'did:web:${host}'#g" $f + sediment "s#export const PUBLIC_BSKY_SERVICE = 'https://public.api.bsky.app'#export const PUBLIC_BSKY_SERVICE = 'https://bsky.${host}'#g" $f + sediment "s#export const PUBLIC_APPVIEW = 'https://api.bsky.app'#export const PUBLIC_APPVIEW = 'https://bsky.${host}'#g" $f + sediment "s#export const PUBLIC_APPVIEW_DID = 'did:web:api.bsky.app'#export const PUBLIC_APPVIEW_DID = 'did:web:bsky.${host}'#g" $f + f=$dt/view/com/util/UserAvatar.tsx curl -sL https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/src/view/com/util/UserAvatar.tsx -o $f - sed -i "s#/img/avatar/plain/#https://cdn.web.syu.is/img/avatar/plain/#g" $f - sed -i "s#/img/avatar_thumbnail/plain/#https://bsky.${host}/img/avatar/plain/#g" $f - sed -i "s#source={{uri: avatar}}#source={{ uri: hackModifyThumbnailPath(avatar, 1 > 0), }}#g" $f + sediment "s#/img/avatar/plain/#https://cdn.web.syu.is/img/avatar/plain/#g" $f + sediment "s#/img/avatar_thumbnail/plain/#https://bsky.${host}/img/avatar/plain/#g" $f + sediment "s#source={{uri: avatar}}#source={{ uri: hackModifyThumbnailPath(avatar, 1 > 0), }}#g" $f curl -sL https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/src/lib/strings/url-helpers.ts -o $dt/lib/strings/url-helpers.ts - sed -i "s#https://go.web.syu.is/redirect?u=\${encodeURIComponent(url)}#\${url}#g" $dt/lib/strings/url-helpers.ts - grep -R $did_admin .|cut -d : -f 1|sort -u|xargs sed -i "s/${did_admin}/${did}/g" + sediment "s#https://go.web.syu.is/redirect?u=\${encodeURIComponent(url)}#\${url}#g" $dt/lib/strings/url-helpers.ts + grep -R $did_admin .|cut -d : -f 1|sort -u|xargs sediment "s/${did_admin}/${did}/g" } @@ -139,7 +154,8 @@ function apply-patch() { pushd ${target_dir} > /dev/null # Check if patch is already applied (reverse dry-run succeeds) - if patch --dry-run -p1 -R < ${patch_file} > /dev/null 2>&1; then + # Use -f to force dry-run to fail instead of asking questions if unapplied + if patch -f --dry-run -p1 -R < ${patch_file} > /dev/null 2>&1; then echo "✅ Already applied - skipping" popd > /dev/null echo "" @@ -147,9 +163,9 @@ function apply-patch() { fi # Check if patch can be applied (forward dry-run succeeds) - if patch --dry-run -p1 < ${patch_file} > /dev/null 2>&1; then + if patch -f --dry-run -p1 < ${patch_file} > /dev/null 2>&1; then echo "🔧 Applying patch..." - if patch -p1 < ${patch_file}; then + if patch -f -p1 < ${patch_file}; then echo "✅ Applied successfully" popd > /dev/null echo "" @@ -284,29 +300,29 @@ function at-repos-ozone-patch() { fi # Replace process.env with env() - sed -i 's/process\.env\.\(NEXT_PUBLIC_[A-Z_]*\)/env('\''\1'\'')/g' lib/constants.ts 2>/dev/null || true - sed -i 's/process\.env\.NODE_ENV/env('\''NODE_ENV'\'')/g' lib/constants.ts 2>/dev/null || true + sediment 's/process\.env\.\(NEXT_PUBLIC_[A-Z_]*\)/env('\''\1'\'')/g' lib/constants.ts 2>/dev/null || true + sediment 's/process\.env\.NODE_ENV/env('\''NODE_ENV'\'')/g' lib/constants.ts 2>/dev/null || true # Add missing SOCIAL_APP_DOMAIN constant after SOCIAL_APP_URL - sed -i '/^export const SOCIAL_APP_URL =/,/^$/{ /^$/a\ + sediment '/^export const SOCIAL_APP_URL =/,/^$/{ /^$/a\ export const SOCIAL_APP_DOMAIN =\ env('\''NEXT_PUBLIC_SOCIAL_APP_DOMAIN'\'') || '\''bsky.app'\''\ }' lib/constants.ts 2>/dev/null || true # Fix multiline process.env patterns - sed -i '/^export const NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process\.env$/,/^ : 7$/ { + sediment '/^export const NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process\.env$/,/^ : 7$/ { s/^export const NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process\.env$/export const NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = env('\''NEXT_PUBLIC_NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS'\'')/ /^ \.NEXT_PUBLIC_NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS$/d }' lib/constants.ts 2>/dev/null || true - sed -i '/^export const YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process\.env$/,/^ : 30$/ { + sediment '/^export const YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process\.env$/,/^ : 30$/ { s/^export const YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process\.env$/export const YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = env('\''NEXT_PUBLIC_YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS'\'')/ /^ \.NEXT_PUBLIC_YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS$/d }' lib/constants.ts 2>/dev/null || true - sed -i '/^export const HIGH_PROFILE_FOLLOWER_THRESHOLD = process\.env$/,/^ : Infinity$/ { + sediment '/^export const HIGH_PROFILE_FOLLOWER_THRESHOLD = process\.env$/,/^ : Infinity$/ { s/^export const HIGH_PROFILE_FOLLOWER_THRESHOLD = process\.env$/export const HIGH_PROFILE_FOLLOWER_THRESHOLD = env('\''NEXT_PUBLIC_HIGH_PROFILE_FOLLOWER_THRESHOLD'\'')/ /^ \.NEXT_PUBLIC_HIGH_PROFILE_FOLLOWER_THRESHOLD$/d }' lib/constants.ts 2>/dev/null || true # Fix parseInt() to handle undefined by adding || '' - sed -i "s/parseInt(env('\([^']*\)'))/parseInt(env('\1') || '0')/g" lib/constants.ts 2>/dev/null || true + sediment "s/parseInt(env('\([^']*\)'))/parseInt(env('\1') || '0')/g" lib/constants.ts 2>/dev/null || true popd > /dev/null } diff --git a/ios/README.md b/ios/README.md new file mode 100644 index 0000000..42c0d3d --- /dev/null +++ b/ios/README.md @@ -0,0 +1,50 @@ +今回の./ios (social-app)開発の要点をまとめます。 + +1. MITのライセンスを遵守すること、iosアプリとして出品しても問題ないようにすること +https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/LICENSE + +2. "Bluesky"という名称を使用しないこと。アイコンの変更。リンクの変更 + +3. selfhostでも動くこと。本来のsocial-appは動きませんので、これは不便なのでiosアプリに出品することにしました。なお、これはすでにpatchで実現しています。 + + +```sh +$ ./install.zsh pull +$ ./install.zsh patch +$ ./ios/setup.zsh +$ ./ios/preview.zsh +``` + +## issue + +1. 最初の画面で、webではちゃんと私のサイトのロゴが表示されていますが、ios モバイル版では、未だにBluesky (icon)です。アカウント作成、サインイン、が表示されています。 + +2. 上のメニューバーにもBlueskyのロゴが表示されています。 + +3. サインイン後のホスティングプロバイダーで中身はsyu.isですが、表示は"Bluesky Social"になっています。これをsyu.isに変更してください。ios/webでコードは異なります。 + +4. チャット機能 +チャット機能は今回無効化するので、下メニューバーやプロフィール、設定画面に表示しないでください。 + +5. 設定ボタン(左カラム)を押すと、フィードバック、ヘルプが表示されますが、非表示にしてください。 + +6. 設定ボタン(左カラム)を押すと、フィード、リスト、保存済みの項目がありますが、これを削除してください。 + +7. 設定ボタン(左カラム)を押すと、下に利用規約、プライバシーポリシーが表示されますが、リンクがbsky.socialです。 +- /about/support/privacy-policy +- /about/support/tos +このページを独自に作って表示してください。 + +8. LOG 09:52:20 (logger) Poll latest failed { + "feed": "following", + "message": "Error: Could not find repo: did:plc:z72i7hdynmk6r22z27h6tvur" +} + +## 壊れた実装 + +1. ログイン後のメイン画面、"Following"の項目(フィード)に表示されるものをシンプルにします。表示するのはFollowingのみで、以下のものを削除してください。 +- おすすめの削除 +- Discoverの削除 +- アカウントを探すの削除 + +2. 誕生日を入力する画面を省略。配布国は限定します。 diff --git a/ios/app-icons/android_icon_core_aurora.png b/ios/app-icons/android_icon_core_aurora.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_core_aurora.png differ diff --git a/ios/app-icons/android_icon_core_bonfire.png b/ios/app-icons/android_icon_core_bonfire.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_core_bonfire.png differ diff --git a/ios/app-icons/android_icon_core_classic.png b/ios/app-icons/android_icon_core_classic.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_core_classic.png differ diff --git a/ios/app-icons/android_icon_core_flat_black.png b/ios/app-icons/android_icon_core_flat_black.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_core_flat_black.png differ diff --git a/ios/app-icons/android_icon_core_flat_blue.png b/ios/app-icons/android_icon_core_flat_blue.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_core_flat_blue.png differ diff --git a/ios/app-icons/android_icon_core_flat_white.png b/ios/app-icons/android_icon_core_flat_white.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_core_flat_white.png differ diff --git a/ios/app-icons/android_icon_core_midnight.png b/ios/app-icons/android_icon_core_midnight.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_core_midnight.png differ diff --git a/ios/app-icons/android_icon_core_sunrise.png b/ios/app-icons/android_icon_core_sunrise.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_core_sunrise.png differ diff --git a/ios/app-icons/android_icon_core_sunset.png b/ios/app-icons/android_icon_core_sunset.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_core_sunset.png differ diff --git a/ios/app-icons/android_icon_default_next.png b/ios/app-icons/android_icon_default_next.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_default_next.png differ diff --git a/ios/app-icons/android_icon_legacy_dark.png b/ios/app-icons/android_icon_legacy_dark.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_legacy_dark.png differ diff --git a/ios/app-icons/android_icon_legacy_light.png b/ios/app-icons/android_icon_legacy_light.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/android_icon_legacy_light.png differ diff --git a/ios/app-icons/ios_icon_core_aurora.png b/ios/app-icons/ios_icon_core_aurora.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_core_aurora.png differ diff --git a/ios/app-icons/ios_icon_core_bonfire.png b/ios/app-icons/ios_icon_core_bonfire.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_core_bonfire.png differ diff --git a/ios/app-icons/ios_icon_core_classic.png b/ios/app-icons/ios_icon_core_classic.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_core_classic.png differ diff --git a/ios/app-icons/ios_icon_core_flat_black.png b/ios/app-icons/ios_icon_core_flat_black.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_core_flat_black.png differ diff --git a/ios/app-icons/ios_icon_core_flat_blue.png b/ios/app-icons/ios_icon_core_flat_blue.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_core_flat_blue.png differ diff --git a/ios/app-icons/ios_icon_core_flat_white.png b/ios/app-icons/ios_icon_core_flat_white.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_core_flat_white.png differ diff --git a/ios/app-icons/ios_icon_core_midnight.png b/ios/app-icons/ios_icon_core_midnight.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_core_midnight.png differ diff --git a/ios/app-icons/ios_icon_core_sunrise.png b/ios/app-icons/ios_icon_core_sunrise.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_core_sunrise.png differ diff --git a/ios/app-icons/ios_icon_core_sunset.png b/ios/app-icons/ios_icon_core_sunset.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_core_sunset.png differ diff --git a/ios/app-icons/ios_icon_default.icon/Assets/iOS transparent.png b/ios/app-icons/ios_icon_default.icon/Assets/iOS transparent.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_default.icon/Assets/iOS transparent.png differ diff --git a/ios/app-icons/ios_icon_default.icon/icon.json b/ios/app-icons/ios_icon_default.icon/icon.json new file mode 100644 index 0000000..8a681cb --- /dev/null +++ b/ios/app-icons/ios_icon_default.icon/icon.json @@ -0,0 +1,31 @@ +{ + "fill" : { + "automatic-gradient" : "srgb:0.00000,0.41569,1.00000,1.00000" + }, + "groups" : [ + { + "layers" : [ + { + "fill" : "none", + "glass" : false, + "image-name" : "iOS transparent.png", + "name" : "iOS transparent" + } + ], + "shadow" : { + "kind" : "neutral", + "opacity" : 0.5 + }, + "translucency" : { + "enabled" : true, + "value" : 0.5 + } + } + ], + "supported-platforms" : { + "circles" : [ + "watchOS" + ], + "squares" : "shared" + } +} \ No newline at end of file diff --git a/ios/app-icons/ios_icon_default.icon/icon.png b/ios/app-icons/ios_icon_default.icon/icon.png new file mode 100644 index 0000000..4c67271 Binary files /dev/null and b/ios/app-icons/ios_icon_default.icon/icon.png differ diff --git a/ios/app-icons/ios_icon_default_next.png b/ios/app-icons/ios_icon_default_next.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_default_next.png differ diff --git a/ios/app-icons/ios_icon_legacy_dark.png b/ios/app-icons/ios_icon_legacy_dark.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_legacy_dark.png differ diff --git a/ios/app-icons/ios_icon_legacy_light.png b/ios/app-icons/ios_icon_legacy_light.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/app-icons/ios_icon_legacy_light.png differ diff --git a/ios/app.config.patch.js b/ios/app.config.patch.js index 136a4d9..1181cde 100644 --- a/ios/app.config.patch.js +++ b/ios/app.config.patch.js @@ -3,7 +3,6 @@ module.exports = { name: 'Aiat', slug: 'aiat', scheme: 'aiat', - owner: 'syui', // Your Expo account - bundleIdentifier: 'ai.syui.at', - // Icon will be set separately + owner: 'syui', + bundleIdentifier: 'ai.syui.at' } diff --git a/ios/bin/build.zsh b/ios/bin/build.zsh deleted file mode 100755 index d1fe8ea..0000000 --- a/ios/bin/build.zsh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/zsh -set -e - -d=~/ai/at/repos/social-app -APP_NAME=Aiat -PKG=aiat -TEAM_NAME= -TEAM_ID= -CERT="Apple Distribution: ${TEAM_NAME} (${TEAM_ID})" -MAIL=user@example.com -KEY_CHAIN=EXAMPLE - -cd $d -# npx expo prebuild --clean -# cd ios && pod install && cd .. - -## アーカイブ -xcodebuild -workspace ios/${PKG}.xcworkspace \ - -scheme ${PKG} \ - -configuration Release \ - -archivePath build/${APP_NAME}.xcarchive \ - -allowProvisioningUpdates \ - archive - -cd build - -# IPA作成 -rm -rf Payload ${APP_NAME}.ipa -mkdir -p Payload -cp -R ${APP_NAME}.xcarchive/Products/Applications/${PKG}.app Payload/ -cp ../store.mobileprovision Payload/${PKG}.app/embedded.mobileprovision - -# entitlements抽出 -security cms -D -i Payload/${PKG}.app/embedded.mobileprovision > /tmp/profile.plist -/usr/libexec/PlistBuddy -x -c "Print :Entitlements" /tmp/profile.plist > /tmp/entitlements.plist - -codesign -f -s "$CERT" Payload/${PKG}.app/Frameworks/*.framework 2>/dev/null || true -codesign -f -s "$CERT" --entitlements /tmp/entitlements.plist Payload/${PKG}.app - -zip -r ${APP_NAME}.ipa Payload - -xcrun altool --upload-app -f ${APP_NAME}.ipa -t ios -u "${MAIL}" -p "@keychain:${KEY_CHAIN}" - -echo "Upload complete" diff --git a/ios/bin/install.zsh b/ios/bin/install.zsh deleted file mode 100644 index 2e372c7..0000000 --- a/ios/bin/install.zsh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/zsh - -if [ "$1" = "social-app-custom" ];then - at-social-app-custom-pages - at-social-app-custom-screens - at-social-app-aiat-config - at-social-app-aiat-logo - at-origin-social-app - exit -fi - -function at-social-app-custom-pages() { - d_=$d/repos/social-app - custom=$d/social-app-custom - - echo "copying custom components to social-app" - - # Create components directory if not exists - mkdir -p ${d_}/src/components/custom - - # Copy custom components - cp ${custom}/PrivacyContent.tsx ${d_}/src/components/custom/ - cp ${custom}/AppInfo.tsx ${d_}/src/components/custom/ - - echo "custom components copied successfully" -} - -function at-social-app-aiat-config() { - d_=$d/repos/social-app - custom=$d/social-app-custom - - echo "applying Aiat configuration" - - # Update app.config.js - cd ${d_} - - # Backup original - cp app.config.js app.config.js.orig - - # Apply changes using sed - sed -i "s/name: 'Bluesky'/name: 'Aiat'/g" app.config.js - sed -i "s/slug: 'bluesky'/slug: 'aiat'/g" app.config.js - sed -i "s/scheme: 'bluesky'/scheme: 'aiat'/g" app.config.js - sed -i "s/owner: 'blueskysocial'/owner: 'syui'/g" app.config.js - sed -i "s/bundleIdentifier: 'xyz.blueskyweb.app'/bundleIdentifier: 'ai.syui.at'/g" app.config.js - - # Update package.json name - sed -i 's/"name": "bsky.app"/"name": "aiat"/g' package.json - - echo "Aiat configuration applied" -} - -function at-social-app-aiat-logo() { - d_=$d/repos/social-app - custom=$d/social-app-custom - - echo "applying Aiat logo" - - # Create logo directory if not exists - mkdir -p ${custom}/assets - - # Copy logo if exists in custom folder - if [ -f ${custom}/assets/icon.png ]; then - cp ${custom}/assets/icon.png ${d_}/assets/app-icons/ios_icon_default_next.png - echo "Aiat logo applied" - else - echo "Warning: Logo file not found at ${custom}/assets/icon.png" - echo "Please add your logo file there" - fi -} - -function at-social-app-custom-screens() { - d_=$d/repos/social-app - custom=$d/social-app-custom - - echo "applying custom screens" - - # Copy custom screen files - cp ${custom}/PrivacyPolicy.screen.tsx ${d_}/src/view/screens/PrivacyPolicy.tsx - cp ${custom}/Support.screen.tsx ${d_}/src/view/screens/Support.tsx - cp ${custom}/LicenseNotice.tsx ${d_}/src/components/custom/ - - echo "custom screens applied" -} - - diff --git a/ios/config.zsh b/ios/config.zsh new file mode 100644 index 0000000..30fc32d --- /dev/null +++ b/ios/config.zsh @@ -0,0 +1,14 @@ +APP_NAME="Aiat" +DEVICE_ID="xxx" +REPO_DIR="../repos/social-app" +APP_SLUG="aiat" +APP_SCHEME="syui" +BUNDLE_ID="ai.syui.at" +APP_GROUP="group.ai.syui.at" +SERVICE_URL="https://syu.is" +HELP_URL="https://syu.is/help" +PRIVACY_URL="https://syu.is/privacy" +TERMS_URL="https://syu.is/terms" +REPO_DIR="../repos/social-app" +CONFIG_FILE="$REPO_DIR/app.config.js" +CONSTANTS_FILE="$REPO_DIR/src/lib/constants.ts" diff --git a/ios/icon.png b/ios/icon.png new file mode 100644 index 0000000..f8f45fb Binary files /dev/null and b/ios/icon.png differ diff --git a/ios/patch_drawer_links.py b/ios/patch_drawer_links.py new file mode 100644 index 0000000..ce038a5 --- /dev/null +++ b/ios/patch_drawer_links.py @@ -0,0 +1,67 @@ +import sys + +file_path = sys.argv[1] +with open(file_path, 'r') as f: + lines = f.readlines() + +new_lines = [] +in_extra_links = False +extra_links_replaced = False + +# We will replace the entire ExtraLinks function +extra_links_code = """ +function ExtraLinks() { + const {_} = useLingui() + const t = useTheme() + const kawaii = useKawaiiMode() + const navigation = useNavigation() + + return ( + + navigation.navigate('TermsOfService')}> + + Terms of Service + + + navigation.navigate('PrivacyPolicy')}> + + Privacy Policy + + + {kawaii && ( + + + Logo by{' '} + + @sawaratsuki.bsky.social + + + + )} + + ) +} +""" + +for line in lines: + if 'function ExtraLinks() {' in line: + in_extra_links = True + new_lines.append(extra_links_code) + continue + + if in_extra_links: + if line.strip() == '}': + in_extra_links = False + # Don't append the closing brace because extra_links_code includes it? + # Wait, extra_links_code includes the whole function. + # So we skip everything until LAST closing brace of function. + # Simple heuristic: indentation. + continue + + new_lines.append(line) + +with open(file_path, 'w') as f: + f.write(''.join(new_lines)) diff --git a/ios/preview.zsh b/ios/preview.zsh new file mode 100755 index 0000000..656caf5 --- /dev/null +++ b/ios/preview.zsh @@ -0,0 +1,63 @@ +#!/bin/zsh +set -e +d=${0:a:h} +cd $d + +source $d/config.zsh + +echo "Running iOS preview workflow..." +cd "$REPO_DIR" + +# 0. Environment Setup (Fix Node Version) +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm +echo "Checking Node version..." +if command -v nvm >/dev/null; then + nvm use 22 || nvm use 20 || echo "Warning: Could not switch to Node 22/20. Current: $(node -v)" +else + echo "nvm not found, using system node: $(node -v)" +fi + +# 1. Install dependencies +echo "1. Installing dependencies (yarn)..." +yarn install + +# 2. Prebuild (Generate ios directory) +echo "2. Running Expo Prebuild..." +# Clean old ios folder to remove old entitlements/AppClip targets +rm -rf ios +npx expo prebuild --platform ios --clean + +# 3. CocoaPods +echo "3. Installing CocoaPods..." +# Ensure PATH includes Homebrew ruby gems if needed +export PATH="/opt/homebrew/lib/ruby/gems/3.4.0/bin:$PATH" +cd ios +pod install +cd .. + +# 4. Signing (Manual Step) +echo "4. Opening Xcode for Signing..." +XCODE_PROJ="ios/${APP_NAME}.xcodeproj" +# Fallback search if variable name logic differs +if [ ! -d "$XCODE_PROJ" ]; then + XCODE_PROJ=$(find ios -name "*.xcodeproj" | head -n 1) +fi + +open "$XCODE_PROJ" +echo "========================================================" +echo " [ACTION REQUIRED] " +echo " Xcode opened ($XCODE_PROJ)." +echo " 1. Go to 'Signing & Capabilities' tab." +echo " 2. Select your Team." +echo " 3. Verify 'App Clip' target is gone." +echo " 4. Ensure no red errors exist." +echo " Press ENTER here once you are done to continue building." +echo "========================================================" +read + +# 5. Run +echo "5. Building and Running..." +# If user wants specific device ID, uncomment below, otherwise let Expo ask/pick boot simulator +# npx expo run:ios --device "$DEVICE_ID" --configuration Release +npx expo run:ios diff --git a/ios/setup.zsh b/ios/setup.zsh new file mode 100755 index 0000000..aa3d6be --- /dev/null +++ b/ios/setup.zsh @@ -0,0 +1,232 @@ +#!/bin/zsh +d=${0:a:h} +cd $d + +source $d/config.zsh + +# Sed compatibility wrapper +function sediment() { + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "$@" + else + sed -i "$@" + fi +} + +echo "Configuring $APP_NAME..." + +# Check if repo exists +#if [ ! -d "$REPO_DIR" ]; then +# echo "Cloning social-app..." +# git clone https://github.com/bluesky-social/social-app "$REPO_DIR" +#else +# echo "Updating social-app..." +# pushd "$REPO_DIR" +# git stash -u +# if ! git pull; then +# echo "Git pull failed. Resetting..." +# git reset --hard HEAD +# git pull +# fi +# popd +#fi + +# Backup config if not exists (or restore from backup to start fresh) +if [ ! -f "$CONFIG_FILE.bak" ]; then + cp "$CONFIG_FILE" "$CONFIG_FILE.bak" +else + cp "$CONFIG_FILE.bak" "$CONFIG_FILE" +fi + +# 1. app.config.js modifications +echo "Updating app.config.js..." + +# Replace name +sediment "s/name: 'Bluesky'/name: '$APP_NAME'/g" "$CONFIG_FILE" +sediment "s/slug: 'bluesky'/slug: '$APP_SLUG'/g" "$CONFIG_FILE" +sediment "s/scheme: 'bsky'/scheme: '$APP_SCHEME'/g" "$CONFIG_FILE" + +# Replace Bundle ID and App Group +sediment "s/xyz.blueskyweb.app/$BUNDLE_ID/g" "$CONFIG_FILE" +sediment "s/group.app.bsky/$APP_GROUP/g" "$CONFIG_FILE" + +# REMOVE App Clip Configuration (Critical for Personal Team Signing) +# Use Python for safer multi-line removal than sed +echo "Removing App Clip configuration..." +python3 -c " +import sys +import re + +try: + with open('$CONFIG_FILE', 'r') as f: + lines = f.readlines() + + with open('$CONFIG_FILE', 'w') as f: + skip = 0 + for i, line in enumerate(lines): + if skip > 0: + skip -= 1 + continue + + # Remove the plugin import line + if 'withStarterPackAppClip.js' in line: + continue + + # Check if this line defines the AppClip target + # Structure we expect: + # { + # targetName: 'BlueskyClip', + # ... + # }, + # We look for the targetName, and if found, we attempt to remove the preceding '{' line if possible + + if \"targetName: 'BlueskyClip'\" in line: + # We found the target. We need to NOT write this line. + # And we need to ensure the PREVIOUS line (which was '{') is not written? + # Since we are writing sequentially, we can't pop easily unless we buffer. + # Actually, simpler: Read file, modify list, write back. + continue + else: + pass + + # Retry with list manipulation approach + out = [] + i = 0 + while i < len(lines): + line = lines[i] + + # Remove plugin import + if 'withStarterPackAppClip.js' in line: + i += 1 + continue + + # Identify the block start + # We look ahead. If lines[i] is '{' and lines[i+1] has 'BlueskyClip', we skip the block. + if i + 1 < len(lines) and lines[i].strip() == '{' and \"targetName: 'BlueskyClip'\" in lines[i+1]: + # Found the start of the block. + # Skip until we find the closing '},' + # Typical block is 4 lines. + # { + # targetName: 'BlueskyClip', + # bundleIdentifier: ..., + # }, + # We'll just skip 4 lines to be safe matching the observed file structure + i += 4 + continue + + out.append(line) + i += 1 + + f.writelines(out) +except Exception as e: + print(f'Error processing file: {e}') + sys.exit(1) +" + +# Inject NSAppTransportSecurity for development/preview (Allow Arbitrary Loads) +if ! grep -q "NSAppTransportSecurity" "$CONFIG_FILE"; then + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "/ios: {/a\\ + infoPlist: {\\ + NSAppTransportSecurity: {\\ + NSAllowsArbitraryLoads: true,\\ + },\\ + }," "$CONFIG_FILE" + else + sed -i "/ios: {/a\\ + infoPlist: {\\ + NSAppTransportSecurity: {\\ + NSAllowsArbitraryLoads: true,\\ + },\\ + }," "$CONFIG_FILE" + fi +fi + +# 2. constants.ts modifications +echo "Updating constants.ts..." +sediment "s|export const BSKY_SERVICE = 'https://bsky.social'|export const BSKY_SERVICE = '$SERVICE_URL'|g" "$CONSTANTS_FILE" +sediment "s|export const BSKY_SERVICE_DID = 'did:web:bsky.social'|export const BSKY_SERVICE_DID = 'did:web:syu.is'|g" "$CONSTANTS_FILE" +sediment "s|export const PUBLIC_BSKY_SERVICE = 'https://public.api.bsky.app'|export const PUBLIC_BSKY_SERVICE = 'https://bsky.syu.is'|g" "$CONSTANTS_FILE" +sediment "s|const HELP_DESK_LANG = 'en-us'|const HELP_DESK_LANG = 'ja-jp'|g" "$CONSTANTS_FILE" +sediment "s|export const HELP_DESK_URL = \`https://blueskyweb.zendesk.com/hc/\${HELP_DESK_LANG}\`|export const HELP_DESK_URL = '$HELP_URL'|g" "$CONSTANTS_FILE" + +# 3. Footer/Link replacements (Global text replacement for specific URLs) +echo "Replacing links..." +grep -r "https://bsky.social/about/blog" "$REPO_DIR/src" -l | xargs -I {} zsh -c "if [[ \"\$OSTYPE\" == \"darwin\"* ]]; then sed -i '' \"s|https://bsky.social/about/blog|$HELP_URL|g\" {}; else sed -i \"s|https://bsky.social/about/blog|$HELP_URL|g\" {}; fi" +grep -r "https://bsky.social/about/blog/jobs" "$REPO_DIR/src" -l | xargs -I {} zsh -c "if [[ \"\$OSTYPE\" == \"darwin\"* ]]; then sed -i '' \"s|https://bsky.social/about/blog/jobs|$HELP_URL|g\" {}; else sed -i \"s|https://bsky.social/about/blog/jobs|$HELP_URL|g\" {}; fi" +grep -r "/support/privacy" "$REPO_DIR/src" -l | xargs -I {} zsh -c "if [[ \"\$OSTYPE\" == \"darwin\"* ]]; then sed -i '' \"s|/support/privacy|$PRIVACY_URL|g\" {}; else sed -i \"s|/support/privacy|$PRIVACY_URL|g\" {}; fi" +grep -r "/support/tos" "$REPO_DIR/src" -l | xargs -I {} zsh -c "if [[ \"\$OSTYPE\" == \"darwin\"* ]]; then sed -i '' \"s|/support/tos|$TERMS_URL|g\" {}; else sed -i \"s|/support/tos|$TERMS_URL|g\" {}; fi" + +# 4. Icon replacement +if [ -d "app-icons" ]; then + echo "Updating icons from app-icons/ directory..." + # Copy the entire contents of the user-provided app-icons directory to the repo's assets/app-icons + # This covers all variants (Aurora, Bonfire, etc.) as the user has prepared them. + cp -rf "app-icons/"* "$REPO_DIR/assets/app-icons/" + + # Also update the main app icons referenced by default + if [ -f "app-icons/ios_icon_default_next.png" ]; then + cp "app-icons/ios_icon_default_next.png" "$REPO_DIR/assets/icon.png" + cp "app-icons/ios_icon_default_next.png" "$REPO_DIR/assets/icon-android-notification.png" + fi + + # Force app.config.js to use the 'default_next' PNG instead of the complex .icon directory + sediment "s|'./assets/app-icons/ios_icon_default.icon'|'./assets/app-icons/ios_icon_default_next.png'|g" "$CONFIG_FILE" + +elif [ -f "icon.png" ]; then + echo "Updating ALL icons from single icon.png..." + # 1. Overwrite the files that app.config.js points to by default + cp "icon.png" "$REPO_DIR/assets/icon.png" + cp "icon.png" "$REPO_DIR/assets/icon-android-notification.png" + + # 2. Overwrite ALL icons in app-icons/ since no specific set was provided + echo "Overwriting all assets/app-icons/*.png..." + find "$REPO_DIR/assets/app-icons" -name "*.png" -exec cp "icon.png" {} \; + + # 3. Handle ios_icon_default.icon special case + TARGET_ICON_DIR="$REPO_DIR/assets/app-icons/ios_icon_default.icon" + if [ -d "$TARGET_ICON_DIR" ]; then + cp "icon.png" "$TARGET_ICON_DIR/icon.png" 2>/dev/null || true + fi + + # 4. Force app.config.js to point to PNG + sediment "s|'./assets/app-icons/ios_icon_default.icon'|'./assets/app-icons/ios_icon_default_next.png'|g" "$CONFIG_FILE" +fi + +# 5. Build Fixes (Entitlements and NSE Sounds) +echo "Applying build fixes..." + +# Fix 1: Create Config Plugin to Allow Entitlements Modification +cat < "$REPO_DIR/plugins/withCodeSignEntitlements.js" +const { withXcodeProject } = require('expo/config-plugins'); + +module.exports = function withCodeSignEntitlements(config) { + return withXcodeProject(config, (config) => { + const xcodeProject = config.modResults; + const configurations = xcodeProject.pbxXCBuildConfigurationSection(); + for (const key in configurations) { + const buildSettings = configurations[key].buildSettings; + if (buildSettings) { + buildSettings['CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION'] = 'YES'; + } + } + return config; + }); +}; +EOF + +# Register the plugin in app.config.js +# We insert it into the plugins array. Finding a safe anchor. +# 'expo-video' is in the plugins array. +sediment "s/'expo-video',/'expo-video', '.\/plugins\/withCodeSignEntitlements.js',/g" "$CONFIG_FILE" + + +# Fix 2: Disable soundFiles in Notification Extension to avoid 'no rule to process dm.aiff' +# The main app handles sounds via expo-notifications. The extension adding it as a source fails. +NOTIF_EXT_FILE="$REPO_DIR/plugins/notificationsExtension/withNotificationsExtension.js" +if [ -f "$NOTIF_EXT_FILE" ]; then + echo "Patching withNotificationsExtension.js..." + sediment "s/const soundFiles = \['dm.aiff'\]/const soundFiles = []/g" "$NOTIF_EXT_FILE" +fi + +echo "Setup complete. App Clip configuration removed. Build fixes applied."