Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ private fun UiTimelineV2.Post.statusMediaFileName(media: UiMedia): String =
statusKey = statusKey.toString(),
userHandle = user?.handle?.canonical ?: "unknown",
media = media,
mediaIndex = images.indexOf(media).coerceAtLeast(0),
)

private fun Context.showTimelineMediaToast(messageRes: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ internal fun StatusMediaScreen(
statusKey = statusKey.toString(),
userHandle = status?.user?.handle?.canonical ?: "unknown",
media = media,
mediaIndex =
state.medias
.takeSuccess()
?.indexOf(media)
?.coerceAtLeast(0)
?: 0,
)
},
fileNames = { medias ->
Expand Down
7 changes: 5 additions & 2 deletions appleApp/ios/UI/Component/IOSTimelineMediaActions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,13 @@ enum IOSTimelineMediaActions {
post: UiTimelineV2.Post,
media: any UiMedia
) -> String {
MediaFileNamePolicy.shared.statusMediaFileName(
let medias = Array(post.images)
let mediaIndex = medias.firstIndex { $0.url == media.url } ?? 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive filenames from the media's actual position

When a status contains multiple audio entries with the same URL, firstIndex returns the first position for every entry, so iOS save-all gives them all the same _01 filename and can overwrite or conflate separate exports (the entries may still differ by headers or metadata). The same URL-only lookup appears in MediaViewerScreen.swift; pass the enumerated/selected position instead of recovering it from a non-unique URL.

Useful? React with 👍 / 👎.

return MediaFileNamePolicy.shared.statusMediaFileName(
statusKey: post.statusKey.description(),
userHandle: post.user?.handle.canonical ?? "unknown",
media: media
media: media,
mediaIndex: Int32(mediaIndex)
)
}

Expand Down
4 changes: 3 additions & 1 deletion appleApp/ios/UI/Screen/MediaViewerScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -436,10 +436,12 @@ struct MediaViewerScreen<SupplementaryOverlay: View>: View {

private func fileName(for media: any UiMedia) -> String {
if let statusKey = shareContext?.statusKey {
let mediaIndex = medias.firstIndex { $0.url == media.url } ?? 0
return MediaFileNamePolicy.shared.statusMediaFileName(
statusKey: statusKey,
userHandle: shareContext?.userHandle ?? "unknown",
media: media
media: media,
mediaIndex: Int32(mediaIndex)
)
}
return MediaFileNamePolicy.shared.rawMediaFileName(media: media)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,5 @@ private fun UiTimelineV2.Post.statusMediaFileName(media: UiMedia): String =
statusKey = statusKey.toString(),
userHandle = user?.handle?.canonical ?: "unknown",
media = media,
mediaIndex = images.indexOf(media).coerceAtLeast(0),
)
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,7 @@ private fun presenter(
statusKey = statusKey.toString(),
userHandle = userHandle,
media = item,
mediaIndex = status.images.indexOf(item).coerceAtLeast(0),
)
val targetFile =
DesktopSaveDialog.chooseFile(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,29 @@ public object MediaFileNamePolicy {
statusKey: String,
userHandle: String,
media: UiMedia,
): String {
val key = sanitizeFileName(statusKey)
val handle = sanitizeFileName(userHandle)
val extension = extensionFromUrl(url = media.url, fallbackExtension = media.fallbackExtension)
return "${key}_$handle.$extension"
}
mediaIndex: Int,
Comment on lines 10 to +11

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update Swift callers for the required media index

When the iOS workflow in .github/workflows/ios.yml regenerates KotlinSharedUI and runs xcodebuild, this required parameter changes the exported Swift signature, but appleApp/ios/UI/Screen/MediaViewerScreen.swift:439-443 and appleApp/ios/UI/Component/IOSTimelineMediaActions.swift:130-134 still invoke it with only three arguments. The iOS target therefore fails to compile with a missing mediaIndex argument; update both Swift helpers to calculate and pass the media's position.

Useful? React with 👍 / 👎.

): String =
statusMediaBaseFileName(
statusKey = statusKey,
userHandle = userHandle,
media = media,
).withIndexSuffix(
index = mediaIndex.coerceAtLeast(0) + 1,
width = 2,
)

public fun statusMediaFileNames(
statusKey: String,
userHandle: String,
medias: List<UiMedia>,
): Map<String, UiMedia> {
val key = sanitizeFileName(statusKey)
val handle = sanitizeFileName(userHandle)
return indexedMediaFileNames(medias) { media ->
val extension = extensionFromUrl(url = media.url, fallbackExtension = media.fallbackExtension)
"${key}_$handle.$extension"
): Map<String, UiMedia> =
indexedMediaFileNames(medias) { media ->
statusMediaBaseFileName(
statusKey = statusKey,
userHandle = userHandle,
media = media,
)
}
}

public fun rawMediaFileName(media: UiMedia): String {
val path = media.url.cleanUrlPath()
Expand Down Expand Up @@ -146,6 +150,17 @@ public object MediaFileNamePolicy {
return lastDotIndex > 0 && lastDotIndex < name.length - 1
}

private fun statusMediaBaseFileName(
statusKey: String,
userHandle: String,
media: UiMedia,
): String {
val key = sanitizeFileName(statusKey)
val handle = sanitizeFileName(userHandle)
val extension = extensionFromUrl(url = media.url, fallbackExtension = media.fallbackExtension)
return "${key}_$handle.$extension"
}

private fun indexedMediaFileNames(
medias: List<UiMedia>,
fileName: (UiMedia) -> String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ class MediaFileNamePolicyTest {
statusKey = "at://did:plc:4ifi6votp7ohf4qre6phovym/app.bsky.feed.post/3mh2lxk5wmc2b",
userHandle = "alice/bob:bsky.social",
media = media,
mediaIndex = 0,
)

assertEquals(
"at___did_plc_4ifi6votp7ohf4qre6phovym_app.bsky.feed.post_3mh2lxk5wmc2b_alice_bob_bsky.social.png",
"at___did_plc_4ifi6votp7ohf4qre6phovym_app.bsky.feed.post_3mh2lxk5wmc2b_alice_bob_bsky.social_01.png",
fileName,
)
}
Expand All @@ -33,9 +34,37 @@ class MediaFileNamePolicyTest {
statusKey = "post123",
userHandle = "alice",
media = media,
mediaIndex = 1,
)

assertEquals("post123_alice.jpeg", fileName)
assertEquals("post123_alice_02.jpeg", fileName)
}

@Test
fun statusMediaFileNameDistinguishesImagesFromTheSameStatus() {
val medias =
listOf(
UiMedia.Image(url = "https://pbs.twimg.com/media/first.jpg"),
UiMedia.Image(url = "https://pbs.twimg.com/media/second.jpg"),
)

val fileNames =
medias.mapIndexed { index, media ->
MediaFileNamePolicy.statusMediaFileName(
statusKey = "tweet123",
userHandle = "alice",
media = media,
mediaIndex = index,
)
}

assertEquals(
listOf(
"tweet123_alice_01.jpg",
"tweet123_alice_02.jpg",
),
fileNames,
)
}

@Test
Expand Down
Loading