fix: prevent pre-existing event notifications on group join
joinedAt was stored on the group record, but foregroundSync and
resyncGroup overwrote it from the Autobase view (which has no
joinedAt). Now joinedAt is persisted as a dedicated Hyperbee key
(joinedAt:{groupId}) that survives all group record writes.
Also preserves joinedAt on group record in foregroundSync/resyncGroup
for member-filtering logic, updates iOS build instructions to prevent
bundle caching issues (--checksum rsync, sim bundle sync).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
cd3832b34d
commit
eaafe11a11
@@ -64,7 +64,7 @@ ssh Tims-Mac-mini.local 'security unlock-keychain -p "" ~/Library/Keychains/buil
|
||||
npx esbuild src/ui/main.jsx --bundle --format=iife --jsx=automatic \
|
||||
--define:process.env.NODE_ENV=\"production\" --outfile=assets/app-ui.bundle
|
||||
# 2. Sync, build, package, install
|
||||
rsync -az --exclude='.git' --exclude='node_modules' --exclude='android' \
|
||||
rsync -az --checksum --exclude='.git' --exclude='node_modules' --exclude='android' \
|
||||
/home/tim/peerloomllc/pearcal-native/ \
|
||||
Tims-Mac-mini.local:~/peerloomllc/pearcal-native/
|
||||
ssh Tims-Mac-mini.local 'export PATH="/opt/homebrew/bin:$PATH" && export LANG=en_US.UTF-8 && \
|
||||
@@ -84,6 +84,7 @@ ideviceinstaller install /tmp/PearCal-release.ipa
|
||||
```bash
|
||||
node_modules/.bin/bare-pack --linked src/bare.js -o assets/bare-universal.bundle
|
||||
node_modules/.bin/bare-pack --host ios-arm64 --linked src/bare.js -o assets/bare-ios.bundle
|
||||
cp assets/bare-ios.bundle assets/bare-ios-sim.bundle
|
||||
npx esbuild src/ui/main.jsx --bundle --format=iife --jsx=automatic \
|
||||
--define:process.env.NODE_ENV=\"production\" --outfile=assets/app-ui.bundle
|
||||
# Then sync + build as above
|
||||
@@ -91,7 +92,7 @@ npx esbuild src/ui/main.jsx --bundle --format=iife --jsx=automatic \
|
||||
|
||||
**Swift/native module changes** (also runs `pod install` first):
|
||||
```bash
|
||||
rsync -az --exclude='.git' --exclude='node_modules' --exclude='android' \
|
||||
rsync -az --checksum --exclude='.git' --exclude='node_modules' --exclude='android' \
|
||||
/home/tim/peerloomllc/pearcal-native/ \
|
||||
Tims-Mac-mini.local:~/peerloomllc/pearcal-native/
|
||||
ssh Tims-Mac-mini.local 'export PATH="/opt/homebrew/bin:$PATH" && export LANG=en_US.UTF-8 && \
|
||||
@@ -107,6 +108,8 @@ rsync -az Tims-Mac-mini.local:/tmp/PearCal-release.ipa /tmp/
|
||||
ideviceinstaller install /tmp/PearCal-release.ipa
|
||||
```
|
||||
|
||||
**iOS bundle caching:** Expo's asset cache survives install-over-top. If iOS behaves differently than expected after a deploy, do a full uninstall first: `ideviceinstaller uninstall com.pearcal` (this wipes app data). Also always keep `bare-ios-sim.bundle` in sync with `bare-ios.bundle` and use `--checksum` with rsync.
|
||||
|
||||
**Note:** New Swift/`.m` files must be registered in `PearCal.xcodeproj/project.pbxproj` via the `xcodeproj` Ruby gem before building. See plan tasks for the helper script.
|
||||
|
||||
**Release (App Store):** Archive and export from Xcode on the Mac Mini. Increment `buildNumber` in `app.json` before each upload.
|
||||
|
||||
+12
-2
@@ -287,6 +287,7 @@ async function reinviteMember (groupId, memberId) {
|
||||
|
||||
async function deleteGroup (id) {
|
||||
await db.del(NS.groups + id)
|
||||
await db.del('joinedAt:' + id).catch(() => {})
|
||||
// Clean up member records
|
||||
for await (const { key } of db.createReadStream({ gt: NS.members + id, lt: NS.members + id + '\xff' })) {
|
||||
await db.del(key)
|
||||
@@ -342,6 +343,13 @@ const pendingMemberLeaves = new Set() // {groupId,memberId} JSON strings, pendi
|
||||
async function joinGroup (group) {
|
||||
if (bases.has(group.id)) return
|
||||
|
||||
// Persist joinedAt as a dedicated key so it survives group record overwrites
|
||||
const joinedAtKey = 'joinedAt:' + group.id
|
||||
const existingJoin = await db.get(joinedAtKey).catch(() => null)
|
||||
if (!existingJoin) {
|
||||
await db.put(joinedAtKey, { ts: group.joinedAt || Date.now() })
|
||||
}
|
||||
|
||||
console.log('Joining group swarm:', group.id)
|
||||
|
||||
const profile = await getProfile()
|
||||
@@ -563,6 +571,7 @@ async function foregroundSync () {
|
||||
name: gNode.value.name || lv?.name,
|
||||
emoji: gNode.value.emoji || lv?.emoji,
|
||||
icon: gNode.value.icon ?? lv?.icon,
|
||||
joinedAt: lv?.joinedAt || gNode.value.joinedAt,
|
||||
nickname: lv?.nickname || gNode.value.nickname,
|
||||
})
|
||||
send({ type: 'event', event: 'sync', data: groupId })
|
||||
@@ -635,6 +644,7 @@ async function resyncGroup (groupId) {
|
||||
name: value.name || ev?.name,
|
||||
emoji: value.emoji || ev?.emoji,
|
||||
icon: value.icon ?? ev?.icon,
|
||||
joinedAt: ev?.joinedAt || value.joinedAt,
|
||||
removedMembers: [...removedMap.values()],
|
||||
members: [...mergedMap.values()]
|
||||
})
|
||||
@@ -798,8 +808,8 @@ function makeApply (groupId) {
|
||||
const eventDate = val.value.date
|
||||
if (eventDate && eventDate < new Date().toISOString().slice(0, 10)) continue
|
||||
// Skip notifications for events that predate our join (initial sync flood)
|
||||
const localGroupJoin = await db.get(NS.groups + groupId).catch(() => null)
|
||||
const joinedAt = localGroupJoin?.value?.joinedAt ?? 0
|
||||
const joinNode = await db.get('joinedAt:' + groupId).catch(() => null)
|
||||
const joinedAt = joinNode?.value?.ts ?? 0
|
||||
if (joinedAt && val.value.updatedAt && val.value.updatedAt < joinedAt) continue
|
||||
// Skip notification if only color changed
|
||||
const onlyColorChanged = localPrev &&
|
||||
|
||||
Reference in New Issue
Block a user