a whole lot of app clip commits...

Revert "another attempt"

This reverts commit adfd562f02defc8d1e031b7a007d352f69eeb274.

Revert "sigh"

This reverts commit de6296d2814165c59d100f18af23df5b94ceb7c4.

sigh

another attempt

okay maybe a solid solution

change some things

and....try again

try again

sigh...only support iphone

fix app config

remove unused files

temp eas update

cleanup plugin

get app clip working

progress

add more to plugin

start working on build plugin

rename

setup app clip

fix created at

oops, wrong workflow

temp workflow edit

add a bunch of libs to exclusion

drop the fork

rm manual config for clip

fix name as well

fix target name
This commit is contained in:
Hailey
2024-06-14 17:02:57 -07:00
parent 988d41161c
commit 6e69b0a987
22 changed files with 285 additions and 91 deletions
@@ -5,6 +5,7 @@ on:
push:
branches:
- main
- starter-packs
workflow_dispatch:
inputs:
channel:
+2 -30
View File
@@ -92,9 +92,6 @@ module.exports = function (config) {
},
entitlements: {
'com.apple.security.application-groups': 'group.app.bsky',
'com.apple.developer.associated-appclip-app-identifiers': [
'xyz.blueskyweb.app.AppClip',
],
},
privacyManifests: {
NSPrivacyAccessedAPITypes: [
@@ -207,21 +204,7 @@ module.exports = function (config) {
sounds: PLATFORM === 'ios' ? ['assets/dm.aiff'] : ['assets/dm.mp3'],
},
],
[
'react-native-app-clip',
{
name: 'BlueskyAppClip',
groupIdentifier: 'group.app.bsky',
excludedPackages: [
'@bam.tech/react-native-image-resizer',
'@braintree/sanitize-url',
'@discord/bottom-sheet',
'@emoji-mart/react',
'@floating-ui/dom',
'@floating-ui/react-dom',
],
},
],
'./plugins/starterPackAppClipExtension/withStarterPackAppClip.js',
'./plugins/withAndroidManifestPlugin.js',
'./plugins/withAndroidManifestFCMIconPlugin.js',
'./plugins/withAndroidStylesWindowBackgroundPlugin.js',
@@ -255,19 +238,8 @@ module.exports = function (config) {
},
},
{
targetName: 'BlueskyAppClip',
targetName: 'BlueskyClip',
bundleIdentifier: 'xyz.blueskyweb.app.AppClip',
entitlements: {
'com.apple.security.application-groups': [
'group.app.bsky',
],
'com.apple.developer.associated-domains':
ASSOCIATED_DOMAINS,
'com.apple.developer.on-demand-install-capable': true,
'com.apple.developer.parent-application-identifiers': [
'xyz.blueskyweb.app',
],
},
},
],
},
@@ -1,6 +1,9 @@
{
"applinks": {
"apps": [],
"appclips": {
"apps": ["B3LX46C5HS.xyz.blueskyweb.app.AppClip"]
},
"details": [
{
"appID": "B3LX46C5HS.xyz.blueskyweb.app",
@@ -10,4 +13,4 @@
}
]
}
}
}
+1 -1
View File
@@ -63,7 +63,7 @@
"testflight": {
"extends": "base",
"ios": {
"autoIncrement": false
"autoIncrement": true
},
"android": {
"autoIncrement": true
+17
View File
@@ -0,0 +1,17 @@
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow()
let controller = ViewController()
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
return true
}
}
+20
View File
@@ -0,0 +1,20 @@
import UIKit
import WebKit
class ViewController: UIViewController {
var webView: WKWebView?
override func viewDidLoad() {
super.viewDidLoad()
let webView = WKWebView(frame: self.view.bounds)
webView.translatesAutoresizingMaskIntoConstraints = false
webView.contentMode = .scaleToFill
self.view.addSubview(webView)
if let url = URL(string: "http://localhost:19006/start/haileyok.com/3kuw7byr7gd2x?clip=true") {
webView.load(URLRequest(url: url))
}
}
}
Binary file not shown.
-1
View File
@@ -165,7 +165,6 @@
"react-dom": "^18.2.0",
"react-keyed-flatten-children": "^3.0.0",
"react-native": "0.74.1",
"react-native-app-clip": "bluesky-social/react-native-app-clip",
"react-native-date-picker": "^4.4.2",
"react-native-drawer-layout": "^4.0.0-alpha.3",
"react-native-fs": "^2.20.0",
@@ -0,0 +1,13 @@
const {withEntitlementsPlist} = require('@expo/config-plugins')
const withAppEntitlements = config => {
// eslint-disable-next-line no-shadow
return withEntitlementsPlist(config, async config => {
config.modResults['com.apple.security.application-groups'] = [
`group.app.bsky`,
]
return config
})
}
module.exports = {withAppEntitlements}
@@ -0,0 +1,32 @@
const {withInfoPlist} = require('@expo/config-plugins')
const plist = require('@expo/plist')
const path = require('path')
const fs = require('fs')
const withClipEntitlements = (config, {targetName}) => {
// eslint-disable-next-line no-shadow
return withInfoPlist(config, config => {
const entitlementsPath = path.join(
config.modRequest.platformProjectRoot,
targetName,
`${targetName}.entitlements`,
)
const appClipEntitlements = {
'com.apple.security.application-groups': [`group.app.bsky`],
'com.apple.developer.parent-application-identifiers': [
`$(AppIdentifierPrefix)${config.ios.bundleIdentifier}`,
],
'com.apple.developer.associated-domains': config.ios.associatedDomains,
}
fs.mkdirSync(path.dirname(entitlementsPath), {
recursive: true,
})
fs.writeFileSync(entitlementsPath, plist.default.build(appClipEntitlements))
return config
})
}
module.exports = {withClipEntitlements}
@@ -0,0 +1,37 @@
const {withInfoPlist} = require('@expo/config-plugins')
const plist = require('@expo/plist')
const path = require('path')
const fs = require('fs')
const withClipInfoPlist = (config, {targetName}) => {
// eslint-disable-next-line no-shadow
return withInfoPlist(config, config => {
const targetPath = path.join(
config.modRequest.platformProjectRoot,
targetName,
'Info.plist',
)
const newPlist = plist.default.build({
NSAppClip: {
NSAppClipRequestEphemeralUserNotification: false,
NSAppClipRequestLocationConfirmation: false,
},
UILaunchScreen: {},
CFBundleName: '$(PRODUCT_NAME)',
CFBundleIdentifier: '$(PRODUCT_BUNDLE_IDENTIFIER)',
CFBundleVersion: '$(CURRENT_PROJECT_VERSION)',
CFBundleExecutable: '$(EXECUTABLE_NAME)',
CFBundlePackageType: '$(PRODUCT_BUNDLE_PACKAGE_TYPE)',
CFBundleShortVersionString: config.version,
UIViewControllerBasedStatusBarAppearance: 'NO',
})
fs.mkdirSync(path.dirname(targetPath), {recursive: true})
fs.writeFileSync(targetPath, newPlist)
return config
})
}
module.exports = {withClipInfoPlist}
@@ -0,0 +1,32 @@
const {withXcodeProject} = require('@expo/config-plugins')
const path = require('path')
const fs = require('fs')
const FILES = ['AppDelegate.swift', 'ViewController.swift']
const withFiles = (config, {targetName}) => {
// eslint-disable-next-line no-shadow
return withXcodeProject(config, config => {
const basePath = path.join(
config.modRequest.projectRoot,
'modules',
targetName,
)
for (const file of FILES) {
const sourcePath = path.join(basePath, file)
const targetPath = path.join(
config.modRequest.platformProjectRoot,
targetName,
file,
)
fs.mkdirSync(path.dirname(targetPath), {recursive: true})
fs.copyFileSync(sourcePath, targetPath)
}
return config
})
}
module.exports = {withFiles}
@@ -0,0 +1,40 @@
const {withPlugins} = require('@expo/config-plugins')
const {withAppEntitlements} = require('./withAppEntitlements')
const {withClipEntitlements} = require('./withClipEntitlements')
const {withClipInfoPlist} = require('./withClipInfoPlist')
const {withFiles} = require('./withFiles')
const {withXcodeTarget} = require('./withXcodeTarget')
const APP_CLIP_TARGET_NAME = 'BlueskyClip'
const withStarterPackAppClip = config => {
return withPlugins(config, [
withAppEntitlements,
[
withClipEntitlements,
{
targetName: APP_CLIP_TARGET_NAME,
},
],
[
withClipInfoPlist,
{
targetName: APP_CLIP_TARGET_NAME,
},
],
[
withFiles,
{
targetName: APP_CLIP_TARGET_NAME,
},
],
[
withXcodeTarget,
{
targetName: APP_CLIP_TARGET_NAME,
},
],
])
}
module.exports = withStarterPackAppClip
@@ -0,0 +1,61 @@
const {withXcodeProject} = require('@expo/config-plugins')
const BUILD_PHASE_FILES = ['AppDelegate.swift', 'ViewController.swift']
const withXcodeTarget = (config, {targetName}) => {
// eslint-disable-next-line no-shadow
return withXcodeProject(config, config => {
const pbxProject = config.modResults
const target = pbxProject.addTarget(targetName, 'watch2_app', targetName)
target.pbxNativeTarget.productType = `"com.apple.product-type.application.on-demand-install-capable"`
pbxProject.addBuildPhase(
BUILD_PHASE_FILES.map(f => `${targetName}/${f}`),
'PBXSourcesBuildPhase',
'Sources',
target.uuid,
)
pbxProject.addBuildPhase(
[],
'PBXResourcesBuildPhase',
'Resources',
target.uuid,
)
const pbxGroupKey = pbxProject.pbxCreateGroup(targetName, targetName)
pbxProject.addFile(`${targetName}/Info.plist`, pbxGroupKey)
const configurations = pbxProject.pbxXCBuildConfigurationSection()
for (const key in configurations) {
if (typeof configurations[key].buildSettings !== 'undefined') {
const buildSettingsObj = configurations[key].buildSettings
if (
typeof buildSettingsObj.PRODUCT_NAME !== 'undefined' &&
buildSettingsObj.PRODUCT_NAME === `"${targetName}"`
) {
buildSettingsObj.CLANG_ENABLE_MODULES = 'YES'
buildSettingsObj.INFOPLIST_FILE = `"${targetName}/Info.plist"`
buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `"${targetName}/${targetName}.entitlements"`
buildSettingsObj.CODE_SIGN_STYLE = 'Automatic'
buildSettingsObj.CURRENT_PROJECT_VERSION = `"${
process.env.BSKY_IOS_BUILD_NUMBER ?? '1'
}"`
buildSettingsObj.GENERATE_INFOPLIST_FILE = 'YES'
buildSettingsObj.MARKETING_VERSION = `"${config.version}"`
buildSettingsObj.PRODUCT_BUNDLE_IDENTIFIER = `"${config.ios?.bundleIdentifier}.AppClip"`
buildSettingsObj.SWIFT_EMIT_LOC_STRINGS = 'YES'
buildSettingsObj.SWIFT_VERSION = '5.0'
buildSettingsObj.TARGETED_DEVICE_FAMILY = `"1"`
buildSettingsObj.DEVELOPMENT_TEAM = 'B3LX46C5HS'
buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET = '14.0'
}
}
}
pbxProject.addTargetAttribute('DevelopmentTeam', 'B3LX46C5HS', targetName)
pbxProject.addTargetAttribute('DevelopmentTeam', 'B3LX46C5HS')
return config
})
}
module.exports = {withXcodeTarget}
+9
View File
@@ -1,6 +1,7 @@
#!/bin/bash
IOS_SHARE_EXTENSION_DIRECTORY="./ios/Share-with-Bluesky"
IOS_NOTIFICATION_EXTENSION_DIRECTORY="./ios/BlueskyNSE"
IOS_APP_CLIP_DIRECTORY="./ios/BlueskyClip"
MODULES_DIRECTORY="./modules"
if [ ! -d $IOS_SHARE_EXTENSION_DIRECTORY ]; then
@@ -16,3 +17,11 @@ if [ ! -d $IOS_NOTIFICATION_EXTENSION_DIRECTORY ]; then
else
cp -R $IOS_NOTIFICATION_EXTENSION_DIRECTORY $MODULES_DIRECTORY
fi
if [ ! -d $IOS_APP_CLIP_DIRECTORY ]; then
echo "$IOS_APP_CLIP_DIRECTORY not found inside of your iOS project."
exit 1
else
cp -R $IOS_APP_CLIP_DIRECTORY $MODULES_DIRECTORY
fi
+3 -3
View File
@@ -26,6 +26,7 @@ export function NewskieDialog({
const control = useDialogControl()
const {joinedViaStarterPack} = profile
const profileName = profile.displayName || `@${profile.handle}`
const createdAt = profile.createdAt ?? 0
return (
<>
@@ -52,8 +53,7 @@ export function NewskieDialog({
joinedViaStarterPack?.record,
) ? (
<Trans>
{profileName} joined Bluesky {ago(profile.createdAt, true)}{' '}
ago with{' '}
{profileName} joined Bluesky {ago(createdAt, true)} ago with{' '}
{joinedViaStarterPack?.creator.did === currentAccount?.did
? 'your'
: `${joinedViaStarterPack?.creator.displayName}'s` ||
@@ -63,7 +63,7 @@ export function NewskieDialog({
) : (
<Trans>
<Text style={[a.font_bold, a.text_md]}>{profileName}</Text>{' '}
recently joined Bluesky {ago(profile.createdAt, true)} ago
recently joined Bluesky {ago(createdAt, true)} ago
</Trans>
)}
</Text>
@@ -9,10 +9,12 @@ export function useStarterPackEntry() {
const url = new URL(window.location.href)
if (url.pathname.startsWith('/start/')) {
const [_, _start, name, rkey] = url.pathname.split('/')
const isClip = url.searchParams.get('clip') === 'true'
if (name && rkey) {
setUsedStarterPack({
uri: window.location.href,
isClip,
})
}
}
+4 -11
View File
@@ -20,19 +20,12 @@ export function ProfileHeaderHandle({
const t = useTheme()
const invalidHandle = isInvalidHandle(profile.handle)
const blockHide = profile.viewer?.blocking || profile.viewer?.blockedBy
const createdAt = new Date(profile.createdAt).getTime()
const createdAt = profile.createdAt
? new Date(profile.createdAt).getTime()
: 0
const isNewskie =
createdAt > 0 &&
Date.now() + 60e3 * 24 * DAYS_TO_SHOW_NEWSKIE >
new Date(profile.createdAt).getTime()
console.log({
date: Date.now() + 60e3 * 24 * DAYS_TO_SHOW_NEWSKIE,
createdAt: new Date(profile.createdAt).getTime(),
})
console.log(isNewskie)
createdAt > 0 && Date.now() + 60e3 * 24 * DAYS_TO_SHOW_NEWSKIE > createdAt
return (
<View
@@ -93,6 +93,7 @@ function LandingScreenInner({
const {_} = useLingui()
const t = useTheme()
const setUsedStarterPack = useSetUsedStarterPack()
const usedStarterPack = useUsedStarterPack()
const {isTabletOrDesktop} = useWebMediaQueries()
const sampleProfiles = listItemsSample?.map(item => item.subject)
@@ -119,6 +120,9 @@ function LandingScreenInner({
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
},
usedStarterPack?.isClip && {
paddingTop: 100,
},
]}>
<View style={[a.flex_row, a.gap_md, a.pb_sm]}>
<Logo width={76} fill="white" />
+1
View File
@@ -93,6 +93,7 @@ export const schema = z.object({
uri: z.string(),
cid: z.string().optional(),
initialFeed: z.string().optional(),
isClip: z.boolean().optional(),
})
.optional(),
})
+1 -1
View File
@@ -3,7 +3,7 @@ import React from 'react'
import * as persisted from '#/state/persisted'
type StateContext =
| {uri: string; cid?: string; initialFeed?: string}
| {uri: string; cid?: string; initialFeed?: string; isClip?: boolean}
| undefined
type SetContext = (v: StateContext) => void
+1 -43
View File
@@ -3403,27 +3403,6 @@
xcode "^3.0.1"
xml2js "0.6.0"
"@expo/config-plugins@~7.2.5":
version "7.2.5"
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.2.5.tgz#b15f22878975fdc4ddcfa8cdc971937ddc4c0249"
integrity sha512-w+5ccu1IxBHgyQk9CPFKLZOk8yZQEyTjbJwOzESK1eR7QwosbcsLkN1c1WWUZYiCXwORu3UTwJYll4+X2xxJhQ==
dependencies:
"@expo/config-types" "^49.0.0-alpha.1"
"@expo/json-file" "~8.2.37"
"@expo/plist" "^0.0.20"
"@expo/sdk-runtime-versions" "^1.0.0"
"@react-native/normalize-color" "^2.0.0"
chalk "^4.1.2"
debug "^4.3.1"
find-up "~5.0.0"
getenv "^1.0.0"
glob "7.1.6"
resolve-from "^5.0.0"
semver "^7.5.3"
slash "^3.0.0"
xcode "^3.0.1"
xml2js "0.6.0"
"@expo/config-plugins@~7.8.0":
version "7.8.0"
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.8.0.tgz#70fd87237faf6a5c3bf47277b67f7b22f9b12c05"
@@ -3446,11 +3425,6 @@
xcode "^3.0.1"
xml2js "0.6.0"
"@expo/config-types@^49.0.0-alpha.1":
version "49.0.0"
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-49.0.0.tgz#15ffef715285c06703f6fb7ec0cda853f645cc09"
integrity sha512-8eyREVi+K2acnMBe/rTIu1dOfyR2+AMnTLHlut+YpMV9OZPdeKV0Bs9BxAewGqBA2slslbQ9N39IS2CuTKpXkA==
"@expo/config-types@^50.0.0-alpha.1":
version "50.0.0"
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-50.0.0.tgz#b534d3ec997ec60f8af24f6ad56244c8afc71a0b"
@@ -3624,7 +3598,7 @@
semver "^7.6.0"
tempy "0.3.0"
"@expo/json-file@^8.2.37", "@expo/json-file@~8.2.37":
"@expo/json-file@^8.2.37":
version "8.2.37"
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.37.tgz#9c02d3b42134907c69cc0a027b18671b69344049"
integrity sha512-YaH6rVg11JoTS2P6LsW7ybS2CULjf40AbnAHw2F1eDPuheprNjARZMnyHFPkKv7GuxCy+B9GPcbOKgc4cgA80Q==
@@ -3725,15 +3699,6 @@
split "^1.0.1"
sudo-prompt "9.1.1"
"@expo/plist@^0.0.20":
version "0.0.20"
resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.0.20.tgz#a6b3124438031c02b762bad5a47b70584d3c0072"
integrity sha512-UXQ4LXCfTZ580LDHGJ5q62jSTwJFFJ1GqBu8duQMThiHKWbMJ+gajJh6rsB6EJ3aLUr9wcauxneL5LVRFxwBEA==
dependencies:
"@xmldom/xmldom" "~0.7.7"
base64-js "^1.2.3"
xmlbuilder "^14.0.0"
"@expo/plist@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.1.0.tgz#eabc95f951d14e10c87fd0443ee01d567371f058"
@@ -18823,13 +18788,6 @@ react-keyed-flatten-children@^3.0.0:
dependencies:
react-is "^18.2.0"
react-native-app-clip@bluesky-social/react-native-app-clip:
version "0.3.0"
resolved "https://codeload.github.com/bluesky-social/react-native-app-clip/tar.gz/05d57c10c5d9799a6bb83d5ee7d1960145c60146"
dependencies:
"@expo/config-plugins" "~7.2.5"
"@expo/plist" "^0.0.20"
react-native-date-picker@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/react-native-date-picker/-/react-native-date-picker-4.4.2.tgz#f7bb9daa8559237e08bd30f907ee8487a6e2a6ec"