From 24ccee8afa393c5dc7c1e60b780d77f549441e47 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 11 Dec 2022 16:52:34 +0100 Subject: [PATCH] Fixed #525 HTML is removed. In this way, if a URL is changed, it can be highlighted as well --- fastlane/metadata/en-US/release_notes.txt | 1 + fastlane/metadata/zh-Hans/release_notes.txt | 1 + package.json | 2 + src/components/Parse/Emojis.tsx | 7 +- src/helpers/removeHTML.ts | 18 +++ src/screens/Tabs/Shared/History.tsx | 117 ++++++++++++-------- yarn.lock | 10 ++ 7 files changed, 104 insertions(+), 52 deletions(-) create mode 100644 src/helpers/removeHTML.ts diff --git a/fastlane/metadata/en-US/release_notes.txt b/fastlane/metadata/en-US/release_notes.txt index 492ae4bc..226b123f 100644 --- a/fastlane/metadata/en-US/release_notes.txt +++ b/fastlane/metadata/en-US/release_notes.txt @@ -1,6 +1,7 @@ Enjoy toooting! This version includes following improvements and fixes: - Automatic setting detected language when tooting - Remember public timeline type selection +- Show diffing of edit history - Added notification for admins - Fix whole word filter matching - Fix tablet cannot delete toot drafts \ No newline at end of file diff --git a/fastlane/metadata/zh-Hans/release_notes.txt b/fastlane/metadata/zh-Hans/release_notes.txt index 4e3b5ced..7ea1cc90 100644 --- a/fastlane/metadata/zh-Hans/release_notes.txt +++ b/fastlane/metadata/zh-Hans/release_notes.txt @@ -1,6 +1,7 @@ toooting愉快!此版本包括以下改进和修复: - 自动识别发嘟语言 - 记住上次公共时间轴选项 +- 显示编辑历史的差异 - 新增管理员推送通知 - 修复过滤整词功能 - 修复平板不能删除草稿 \ No newline at end of file diff --git a/package.json b/package.json index 53bef058..82ed917a 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "@sharcoux/slider": "^6.1.1", "@tanstack/react-query": "^4.19.1", "axios": "^0.27.2", + "diff": "^5.1.0", "expo": "^47.0.8", "expo-auth-session": "^3.7.3", "expo-av": "^13.0.2", @@ -101,6 +102,7 @@ "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.18.6", "@expo/config": "^7.0.3", + "@types/diff": "^5.0.2", "@types/linkify-it": "^3.0.2", "@types/lodash": "^4.14.191", "@types/react": "~18.0.26", diff --git a/src/components/Parse/Emojis.tsx b/src/components/Parse/Emojis.tsx index fe8fac22..d9e1e88b 100644 --- a/src/components/Parse/Emojis.tsx +++ b/src/components/Parse/Emojis.tsx @@ -5,7 +5,7 @@ import { StyleConstants } from '@utils/styles/constants' import { adaptiveScale } from '@utils/styles/scaling' import { useTheme } from '@utils/styles/ThemeManager' import React, { useMemo } from 'react' -import { Platform, StyleSheet } from 'react-native' +import { Platform, StyleSheet, TextStyle } from 'react-native' import FastImage from 'react-native-fast-image' import { useSelector } from 'react-redux' import validUrl from 'valid-url' @@ -18,10 +18,11 @@ export interface Props { size?: 'S' | 'M' | 'L' adaptiveSize?: boolean fontBold?: boolean + style?: TextStyle } const ParseEmojis = React.memo( - ({ content, emojis, size = 'M', adaptiveSize = false, fontBold = false }: Props) => { + ({ content, emojis, size = 'M', adaptiveSize = false, fontBold = false, style }: Props) => { const { reduceMotionEnabled } = useAccessibility() const adaptiveFontsize = useSelector(getSettingsFontsize) @@ -51,7 +52,7 @@ const ParseEmojis = React.memo( }, [theme, adaptiveFontsize]) return ( - + {emojis ? ( content .split(regexEmoji) diff --git a/src/helpers/removeHTML.ts b/src/helpers/removeHTML.ts new file mode 100644 index 00000000..8690061a --- /dev/null +++ b/src/helpers/removeHTML.ts @@ -0,0 +1,18 @@ +import htmlparser2 from 'htmlparser2-without-node-native' + +const removeHTML = (text: string): string => { + let raw: string = '' + + const parser = new htmlparser2.Parser({ + ontext: (text: string) => { + raw = raw + text + } + }) + + parser.write(text) + parser.end() + + return raw +} + +export default removeHTML diff --git a/src/screens/Tabs/Shared/History.tsx b/src/screens/Tabs/Shared/History.tsx index fc9a9d3c..1c59cfd8 100644 --- a/src/screens/Tabs/Shared/History.tsx +++ b/src/screens/Tabs/Shared/History.tsx @@ -4,44 +4,86 @@ import { ParseEmojis } from '@components/Parse' import ComponentSeparator from '@components/Separator' import CustomText from '@components/Text' import TimelineAttachment from '@components/Timeline/Shared/Attachment' -import TimelineContent from '@components/Timeline/Shared/Content' import StatusContext from '@components/Timeline/Shared/Context' import HeaderSharedCreated from '@components/Timeline/Shared/HeaderShared/Created' +import removeHTML from '@helpers/removeHTML' import { TabSharedStackScreenProps } from '@utils/navigation/navigators' import { useStatusHistory } from '@utils/queryHooks/statusesHistory' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' +import { diffWords } from 'diff' import React, { useEffect } from 'react' import { useTranslation } from 'react-i18next' import { FlatList, View } from 'react-native' -const ContentView: React.FC<{ item: Mastodon.StatusHistory }> = ({ item }) => { +const ContentView: React.FC<{ + item: Mastodon.StatusHistory + prevItem?: Mastodon.StatusHistory +}> = ({ item, prevItem }) => { const { colors } = useTheme() + const changesSpoiler = diffWords( + removeHTML(prevItem?.spoiler_text || item.spoiler_text || ''), + removeHTML(item.spoiler_text || '') + ) + const changesContent = diffWords( + removeHTML(prevItem?.content || item.content), + removeHTML(item.content) + ) + return ( // @ts-ignore - - - {item.poll?.options.map((option, index) => ( - - - + + {changesSpoiler.length && changesSpoiler[0].count ? ( + + {changesSpoiler.map(({ value, added, removed }, index) => ( + + ))} + + ) : null} + + {changesContent.map(({ value, added, removed }, index) => ( + - - - + ))} + + {item.poll?.options.map((option, index) => ( + + + + + + + - - ))} - + ))} + + ) } @@ -62,41 +104,18 @@ const TabSharedHistory: React.FC }) }, []) + const dataReversed = data ? [...data].reverse() : [] + return ( 0 - ? data - .slice(0) - .reverse() - .filter((_, index) => index !== 0) - : [] - } - renderItem={({ item }) => } - ItemSeparatorComponent={() => ( - + style={{ flex: 1, minHeight: '100%' }} + data={dataReversed} + renderItem={({ item, index }) => ( + )} + ItemSeparatorComponent={ComponentSeparator} /> ) - - // return ( - // - // {data && data.length > 0 - // ? data - // .slice(0) - // .reverse() - // .map((d, i) => - // i !== 0 ? ( - // - // ) : null - // ) - // : null} - // - // ) } export default TabSharedHistory diff --git a/yarn.lock b/yarn.lock index e40a5cab..064cea28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2683,6 +2683,11 @@ "@types/node" "*" "@types/responselike" "^1.0.0" +"@types/diff@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@types/diff/-/diff-5.0.2.tgz#dd565e0086ccf8bc6522c6ebafd8a3125c91c12b" + integrity sha512-uw8eYMIReOwstQ0QKF0sICefSy8cNO/v7gOTiIy9SbwuHyEecJUm7qlgueOO5S1udZ5I/irVydHVwMchgzbKTg== + "@types/glob@^7.1.1": version "7.2.0" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" @@ -5256,6 +5261,11 @@ detect-port-alt@1.1.6: address "^1.0.1" debug "^2.6.0" +diff@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"