Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 365f44dbe4 | |||
| 40c2ce20f3 | |||
| aa516667cd | |||
| f6fcf35cf8 |
@@ -7,8 +7,11 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
if: github.server_url == 'https://github.com'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 30
|
timeout-minutes: 60
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -27,22 +30,52 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: 9
|
version: 9
|
||||||
|
|
||||||
|
- name: Get pnpm store path
|
||||||
|
id: pnpm-cache
|
||||||
|
shell: bash
|
||||||
|
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Cache pnpm store
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
||||||
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pnpm-
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
working-directory: artifacts/postiz-mobile
|
working-directory: artifacts/postiz-mobile
|
||||||
run: pnpm install --no-frozen-lockfile
|
run: pnpm install --no-frozen-lockfile
|
||||||
|
|
||||||
- name: Install Expo CLI
|
|
||||||
run: pnpm add -g expo-cli@latest || true
|
|
||||||
|
|
||||||
- name: Set up Android SDK
|
- name: Set up Android SDK
|
||||||
uses: android-actions/setup-android@v3
|
uses: android-actions/setup-android@v3
|
||||||
|
|
||||||
- name: Accept Android SDK licenses
|
- name: Accept Android SDK licenses
|
||||||
run: yes | sdkmanager --licenses || true
|
run: yes | sdkmanager --licenses || true
|
||||||
|
|
||||||
|
- name: Cache Android NDK
|
||||||
|
id: ndk-cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: /usr/local/lib/android/sdk/ndk/28.2.13676358
|
||||||
|
key: ndk-28.2.13676358-v1
|
||||||
|
|
||||||
- name: Install SDK components
|
- name: Install SDK components
|
||||||
run: |
|
run: |
|
||||||
sdkmanager "platform-tools" "platforms;android-35" "build-tools;35.0.0" "ndk;28.2.13676358"
|
sdkmanager "platform-tools" "platforms;android-35" "build-tools;35.0.0"
|
||||||
|
if [ "${{ steps.ndk-cache.outputs.cache-hit }}" != "true" ]; then
|
||||||
|
sdkmanager "ndk;28.2.13676358"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Cache Gradle
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.gradle/caches
|
||||||
|
~/.gradle/wrapper
|
||||||
|
key: ${{ runner.os }}-gradle-${{ hashFiles('artifacts/postiz-mobile/package.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-gradle-
|
||||||
|
|
||||||
- name: Decode keystore
|
- name: Decode keystore
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import DateTimePicker from "@react-native-community/datetimepicker";
|
|||||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||||
import * as Haptics from "expo-haptics";
|
import * as Haptics from "expo-haptics";
|
||||||
import { Image } from "expo-image";
|
import { Image } from "expo-image";
|
||||||
|
import * as ImageManipulator from "expo-image-manipulator";
|
||||||
import * as ImagePicker from "expo-image-picker";
|
import * as ImagePicker from "expo-image-picker";
|
||||||
import { fetch as expoFetch } from "expo/fetch";
|
import { fetch as expoFetch } from "expo/fetch";
|
||||||
import { useLocalSearchParams } from "expo-router";
|
import { useLocalSearchParams } from "expo-router";
|
||||||
@@ -146,10 +147,25 @@ export default function ComposeScreen() {
|
|||||||
const result = await ImagePicker.launchImageLibraryAsync({
|
const result = await ImagePicker.launchImageLibraryAsync({
|
||||||
mediaTypes: ["images"],
|
mediaTypes: ["images"],
|
||||||
allowsEditing: false,
|
allowsEditing: false,
|
||||||
quality: 0.85,
|
quality: 1,
|
||||||
});
|
});
|
||||||
if (!result.canceled && result.assets[0]) {
|
if (!result.canceled && result.assets[0]) {
|
||||||
setImageUri(result.assets[0].uri);
|
const asset = result.assets[0];
|
||||||
|
const MAX_DIM = 1920;
|
||||||
|
const w = asset.width ?? 0;
|
||||||
|
const h = asset.height ?? 0;
|
||||||
|
const needsResize = w > MAX_DIM || h > MAX_DIM;
|
||||||
|
if (needsResize) {
|
||||||
|
const landscape = w >= h;
|
||||||
|
const resized = await ImageManipulator.manipulateAsync(
|
||||||
|
asset.uri,
|
||||||
|
[{ resize: landscape ? { width: MAX_DIM } : { height: MAX_DIM } }],
|
||||||
|
{ compress: 0.85, format: ImageManipulator.SaveFormat.JPEG }
|
||||||
|
);
|
||||||
|
setImageUri(resized.uri);
|
||||||
|
} else {
|
||||||
|
setImageUri(asset.uri);
|
||||||
|
}
|
||||||
setExistingMedia([]);
|
setExistingMedia([]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { PostCard } from "@/components/PostCard";
|
|||||||
import { PostizPost, usePostiz } from "@/context/PostizContext";
|
import { PostizPost, usePostiz } from "@/context/PostizContext";
|
||||||
import { useColors } from "@/hooks/useColors";
|
import { useColors } from "@/hooks/useColors";
|
||||||
import { extractError } from "@/lib/extractError";
|
import { extractError } from "@/lib/extractError";
|
||||||
|
import { stripHtml } from "@/lib/stripHtml";
|
||||||
|
|
||||||
const SORT_STORAGE_KEY = "postiz_posts_sort";
|
const SORT_STORAGE_KEY = "postiz_posts_sort";
|
||||||
|
|
||||||
@@ -193,14 +194,15 @@ export default function PostsScreen() {
|
|||||||
const showContextMenu = (post: PostizPost) => {
|
const showContextMenu = (post: PostizPost) => {
|
||||||
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
|
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
|
||||||
|
|
||||||
const preview = post.content.slice(0, 60) + (post.content.length > 60 ? "…" : "");
|
const plain = stripHtml(post.content);
|
||||||
|
const preview = plain.slice(0, 60) + (plain.length > 60 ? "…" : "");
|
||||||
|
|
||||||
const buttons: Array<{ text: string; style?: "cancel" | "destructive" | "default"; onPress?: () => void }> = [];
|
const buttons: Array<{ text: string; style?: "cancel" | "destructive" | "default"; onPress?: () => void }> = [];
|
||||||
|
|
||||||
buttons.push({
|
buttons.push({
|
||||||
text: "Copy text",
|
text: "Copy text",
|
||||||
onPress: async () => {
|
onPress: async () => {
|
||||||
await Clipboard.setStringAsync(post.content);
|
await Clipboard.setStringAsync(stripHtml(post.content));
|
||||||
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
|
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
|
||||||
setCopyToast(true);
|
setCopyToast(true);
|
||||||
setTimeout(() => setCopyToast(false), 2000);
|
setTimeout(() => setCopyToast(false), 2000);
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 652 KiB After Width: | Height: | Size: 49 KiB |
@@ -12,6 +12,7 @@ import {
|
|||||||
import { Swipeable } from "react-native-gesture-handler";
|
import { Swipeable } from "react-native-gesture-handler";
|
||||||
import { useColors } from "@/hooks/useColors";
|
import { useColors } from "@/hooks/useColors";
|
||||||
import { PostizPost } from "@/context/PostizContext";
|
import { PostizPost } from "@/context/PostizContext";
|
||||||
|
import { stripHtml } from "@/lib/stripHtml";
|
||||||
import { StatusBadge } from "./StatusBadge";
|
import { StatusBadge } from "./StatusBadge";
|
||||||
|
|
||||||
interface PostCardProps {
|
interface PostCardProps {
|
||||||
@@ -118,10 +119,11 @@ export function PostCard({ post, onDelete, onLongPress, onReschedule }: PostCard
|
|||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const integrations = post.integrations ?? (post.integration ? [post.integration] : []);
|
const integrations = post.integrations ?? (post.integration ? [post.integration] : []);
|
||||||
|
const plainContent = stripHtml(post.content);
|
||||||
const truncatedContent =
|
const truncatedContent =
|
||||||
post.content.length > 140
|
plainContent.length > 140
|
||||||
? post.content.slice(0, 140) + "…"
|
? plainContent.slice(0, 140) + "…"
|
||||||
: post.content;
|
: plainContent;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Swipeable
|
<Swipeable
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
export function stripHtml(html: string): string {
|
||||||
|
return html
|
||||||
|
.replace(/<br\s*\/?>/gi, "\n")
|
||||||
|
.replace(/<\/p>/gi, "\n")
|
||||||
|
.replace(/<[^>]+>/g, "")
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, "'")
|
||||||
|
.replace(/ /g, " ")
|
||||||
|
.replace(/\n{3,}/g, "\n\n")
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
"expo-glass-effect": "~0.1.4",
|
"expo-glass-effect": "~0.1.4",
|
||||||
"expo-haptics": "~15.0.8",
|
"expo-haptics": "~15.0.8",
|
||||||
"expo-image": "~3.0.11",
|
"expo-image": "~3.0.11",
|
||||||
|
"expo-image-manipulator": "~13.0.6",
|
||||||
"expo-image-picker": "~17.0.9",
|
"expo-image-picker": "~17.0.9",
|
||||||
"expo-linear-gradient": "~15.0.8",
|
"expo-linear-gradient": "~15.0.8",
|
||||||
"expo-linking": "~8.0.10",
|
"expo-linking": "~8.0.10",
|
||||||
|
|||||||
Reference in New Issue
Block a user