ai/at
1
0

add ios social-app

This commit is contained in:
2025-12-06 21:14:08 +09:00
parent 948551c185
commit f47f219e4b
36 changed files with 393 additions and 156 deletions

8
ios/README.md Normal file
View File

@@ -0,0 +1,8 @@
今回の./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で実現しています。

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -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'
}

View File

@@ -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"

View File

@@ -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"
}

14
ios/config.zsh Normal file
View File

@@ -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"

BIN
ios/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

65
ios/preview.zsh Executable file
View File

@@ -0,0 +1,65 @@
#!/bin/zsh
set -e
d=${0:a:h}
cd $d
# DEVICE_ID="00008110-001855EA36D0401E"
APP_NAME="syuis"
REPO_DIR="../repos/social-app"
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

244
ios/setup.zsh Executable file
View File

@@ -0,0 +1,244 @@
#!/bin/zsh
d=${0:a:h}
cd $d
APP_NAME="syuis"
APP_SLUG="syuis"
APP_SCHEME="syui"
BUNDLE_ID="is.syu"
APP_GROUP="group.is.syu"
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"
# 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 <<EOF > "$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."