Skip to content
Merged
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
17 changes: 17 additions & 0 deletions apps/desktop/changelog/1.12.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# What's new in v1.12.0

## Improvements

- Hardened custom URL integrations so only trusted protocols can be opened
- Improved the error shown when an RSSHub subscription limit is reached

## No longer broken

- Fixed share popovers remaining open after completing an action
- Fixed plan upgrades for past-due Stripe subscriptions
- Restored category chevron rotation
- Restored correct border styling across the app

## Thanks

Special thanks to volunteer contributor @sebastionoss for hardening custom URL integrations
6 changes: 3 additions & 3 deletions apps/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "Folo",
"type": "module",
"version": "1.11.0",
"version": "1.12.0",
"private": true,
"description": "Follow everything in one place",
"author": "Folo Team",
Expand Down Expand Up @@ -99,7 +99,7 @@
"workbox-build": "7.4.1",
"workbox-window": "7.4.1"
},
"runtimeVersion": "1.11.0",
"runtimeVersion": "1.12.0",
"productName": "Folo",
"mainHash": "b672f321b6478cbaad0ad6e354d73ca3c8a79f90aaadb41c119499639ec66e87"
"mainHash": "0fdc4db0cd19e2c2d6cf6c596aa1a62cc253b4c9612633470cb6b8d64fba403a"
}
2 changes: 1 addition & 1 deletion apps/desktop/release.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.11.0",
"version": "1.12.0",
"mode": "build",
"runtimeVersion": null,
"channel": null
Expand Down
16 changes: 15 additions & 1 deletion apps/mobile/app.config.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,17 @@ export default ({ config }: ConfigContext): ExpoConfig => {
},
android: {
package: "is.follow",
// Media selection uses system pickers; saving only needs write access on older Android versions.
blockedPermissions: [
"android.permission.ACCESS_MEDIA_LOCATION",
"android.permission.CAMERA",
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.READ_MEDIA_AUDIO",
"android.permission.READ_MEDIA_IMAGES",
"android.permission.READ_MEDIA_VIDEO",
"android.permission.READ_MEDIA_VISUAL_USER_SELECTED",
"android.permission.RECORD_AUDIO",
],
adaptiveIcon: {
foregroundImage: adaptiveIconPath,
monochromeImage: adaptiveIconPath,
Expand Down Expand Up @@ -158,7 +169,8 @@ export default ({ config }: ConfigContext): ExpoConfig => {
{
photosPermission: "Allow $(PRODUCT_NAME) to access your photos.",
savePhotosPermission: "Allow $(PRODUCT_NAME) to save photos.",
isAccessMediaLocationEnabled: true,
isAccessMediaLocationEnabled: false,
granularPermissions: [],
},
],
"expo-apple-authentication",
Expand Down Expand Up @@ -192,6 +204,8 @@ export default ({ config }: ConfigContext): ExpoConfig => {
"expo-image-picker",
{
photosPermission: "Allow $(PRODUCT_NAME) to access your photos.",
cameraPermission: false,
microphonePermission: false,
},
],
[
Expand Down
5 changes: 5 additions & 0 deletions apps/mobile/changelog/0.5.8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# What's New in v0.5.8

## Improvements

- Updated Android photo selection and saving to use system pickers and request only the permissions required
4 changes: 2 additions & 2 deletions apps/mobile/ios/Folo/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>0.5.7</string>
<string>0.5.8</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
Expand All @@ -54,7 +54,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>10</string>
<string>11</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationCategoryType</key>
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@follow/mobile",
"version": "0.5.7",
"version": "0.5.8",
"private": true,
"main": "src/main.tsx",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/release.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "0.5.7",
"version": "0.5.8",
"mode": "store",
"runtimeVersion": null,
"channel": null
Expand Down
41 changes: 40 additions & 1 deletion apps/mobile/scripts/app-config.base.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest"

import { resolveRuntimeVersion } from "../app.config.base"
import createExpoConfig, { resolveRuntimeVersion } from "../app.config.base"

describe("resolveRuntimeVersion", () => {
it("keeps the development runtime version stable", () => {
Expand Down Expand Up @@ -33,3 +33,42 @@ describe("resolveRuntimeVersion", () => {
).toThrow(/OTA_RUNTIME_VERSION/i)
})
})

describe("Android media permissions", () => {
const config = createExpoConfig({
config: {},
} as Parameters<typeof createExpoConfig>[0])

it("blocks broad media access that is not required by the app", () => {
expect(config.android?.blockedPermissions).toEqual([
"android.permission.ACCESS_MEDIA_LOCATION",
"android.permission.CAMERA",
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.READ_MEDIA_AUDIO",
"android.permission.READ_MEDIA_IMAGES",
"android.permission.READ_MEDIA_VIDEO",
"android.permission.READ_MEDIA_VISUAL_USER_SELECTED",
"android.permission.RECORD_AUDIO",
])
})

it("configures media APIs for picker and write-only access", () => {
expect(config.plugins).toContainEqual([
"expo-media-library",
{
photosPermission: "Allow $(PRODUCT_NAME) to access your photos.",
savePhotosPermission: "Allow $(PRODUCT_NAME) to save photos.",
isAccessMediaLocationEnabled: false,
granularPermissions: [],
},
])
expect(config.plugins).toContainEqual([
"expo-image-picker",
{
photosPermission: "Allow $(PRODUCT_NAME) to access your photos.",
cameraPermission: false,
microphonePermission: false,
},
])
})
})
6 changes: 3 additions & 3 deletions apps/mobile/src/components/ui/image/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { IMAGE_PROXY_URL } from "@follow/utils/img-proxy"
import ImageEditor from "@react-native-community/image-editor"
import * as FileSystem from "expo-file-system/legacy"
import type { ImageProps, ImageSource } from "expo-image"
import { saveToLibraryAsync, usePermissions } from "expo-media-library"
import { Asset, usePermissions } from "expo-media-library"
import * as Sharing from "expo-sharing"
import { useCallback } from "react"
import { Image } from "react-native"
Expand Down Expand Up @@ -145,7 +145,7 @@ export const saveImageToMediaLibrary = async ({ uri }: { uri: string }) => {
const croppedImage = await getImageData(uri)
const filename = `${extractFilenameFromUrl(uri)}.png`
const { filePath, cleanup } = await createTempFile(croppedImage.base64, filename)
await saveToLibraryAsync(filePath)
await Asset.create(filePath)
cleanup()
}

Expand All @@ -161,7 +161,7 @@ export const saveImageToMediaLibrary = async ({ uri }: { uri: string }) => {
*/
export function useSaveImageToMediaLibrary() {
const [permissionResponse, requestPermission, getPermission] = usePermissions({
granularPermissions: ["photo"],
writeOnly: true,
})
return useCallback(
async (uri: string) => {
Expand Down
Loading