Skip to content

Commit 8ab1f70

Browse files
authored
Merge pull request #4691 from RSSNext/hotfix/11.11
chore(desktop): Release v1.1.2 for hotfix
2 parents cdd7506 + 7d446b2 commit 8ab1f70

File tree

14 files changed

+90
-63
lines changed

14 files changed

+90
-63
lines changed

apps/desktop/layer/main/src/updater/configs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export const appUpdaterConfig = {
99

1010
// Disable app update will also disable renderer hot update and core update
1111
enableAppUpdate: true,
12-
enableDistributionStoreUpdate: true,
12+
enableDistributionStoreUpdate: isStoreDistribution,
1313

1414
app: {
1515
autoCheckUpdate: true,

apps/desktop/layer/main/src/updater/index.ts

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -116,25 +116,8 @@ class FollowUpdater {
116116
}
117117

118118
const payload = await getUpdateInfo(options.refresh ? { refresh: true } : {})
119-
const { decision } = payload
120119

121-
if (!decision || decision.type === "none") {
122-
logger.info("Update decision: none")
123-
return { hasUpdate: false }
124-
}
125-
126-
if (decision.type === "renderer") {
127-
logger.info("Update decision: renderer")
128-
return await this.handleRendererDecision(payload)
129-
}
130-
131-
if (decision.type === "app") {
132-
logger.info("Update decision: app")
133-
return await this.handleAppDecision(payload)
134-
}
135-
136-
logger.warn("Unknown update decision type", { type: decision.type })
137-
return { hasUpdate: false }
120+
return this.handleDirectAppDecision(payload)
138121
} catch (error) {
139122
logger.error("Failed to check for updates", error)
140123
return { hasUpdate: false, error: error instanceof Error ? error.message : "Unknown error" }
@@ -143,6 +126,28 @@ class FollowUpdater {
143126
}
144127
}
145128

129+
async handleDirectAppDecision(payload: LatestReleasePayload): Promise<UpdateCheckResult> {
130+
const { decision } = payload
131+
132+
if (!decision || decision.type === "none") {
133+
logger.info("Update decision: none")
134+
return { hasUpdate: false }
135+
}
136+
137+
if (decision.type === "renderer") {
138+
logger.info("Update decision: renderer")
139+
return await this.handleRendererDecision(payload)
140+
}
141+
142+
if (decision.type === "app") {
143+
logger.info("Update decision: app")
144+
return await this.handleAppDecision(payload)
145+
}
146+
147+
logger.warn("Unknown update decision type", { type: decision.type })
148+
return { hasUpdate: false }
149+
}
150+
146151
async downloadAppUpdate(): Promise<void> {
147152
if (this.disabled || this.downloadingUpdate) {
148153
return
@@ -266,8 +271,11 @@ class FollowUpdater {
266271
const info = await getDistributionUpdateInfo()
267272

268273
if (!info) {
269-
logger.info("Distribution update info unavailable for current build")
270-
return { hasUpdate: false }
274+
logger.info(
275+
"Distribution update info unavailable for current build, falling back to direct app decision",
276+
)
277+
const payload = await getUpdateInfo()
278+
return this.handleDirectAppDecision(payload)
271279
}
272280

273281
const rendererResult = await this.tryDistributionRendererUpdate(info.rendererUpdate)

apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/AISmartSidebar.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
.ai-glass-layer-1,
55
.ai-glass-layer-2,
66
.ai-glass-layer-3 {
7-
transform-origin: right center;
7+
transform-origin: right bottom;
88
transition:
99
width 0.5s cubic-bezier(0.23, 1, 0.32, 1),
1010
opacity 0.5s cubic-bezier(0.23, 1, 0.32, 1),

apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/AISmartSidebar.tsx

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ const AIAmbientSidebar: React.FC<{ onExpand: () => void }> = ({ onExpand }) => {
4545
const alpha = value <= 0.4 ? 0 : (value - 0.4) * 0.12
4646
return `radial-gradient(ellipse at center, rgba(255, 92, 0, ${alpha}) 0%, transparent 70%)`
4747
})
48-
const glowX = useTransform(intensity, (value) => value * -20)
48+
const glowX = useTransform(intensity, (value) => value * -12)
49+
const glowY = useTransform(intensity, (value) => value * -24)
4950

5051
const canShowPrompt = useGlobalFocusableScopeSelector(FocusablePresets.isNotFloatingLayerScope)
5152
useEffect(() => {
@@ -58,13 +59,15 @@ const AIAmbientSidebar: React.FC<{ onExpand: () => void }> = ({ onExpand }) => {
5859
return
5960
}
6061

61-
const maxDistance = 500
62-
const threshold = 80
63-
const showedThreshold = 300
64-
const topBoundary = 100
62+
const effectWidth = 220
63+
const effectHeight = 220
64+
const activationWidth = 50
65+
const activationHeight = 50
66+
const releaseWidth = 90
67+
const releaseHeight = 90
6568
const frameRef = { current: null as number | null }
6669

67-
const hidePrompt = () => {
70+
const resetState = () => {
6871
intensity.set(0)
6972
if (isShowPromptRef.current) {
7073
isShowPromptRef.current = false
@@ -82,27 +85,31 @@ const AIAmbientSidebar: React.FC<{ onExpand: () => void }> = ({ onExpand }) => {
8285
frameRef.current = null
8386

8487
const rightEdgeDistance = window.innerWidth - clientX
88+
const bottomEdgeDistance = window.innerHeight - clientY
89+
const withinEffectZone =
90+
rightEdgeDistance <= effectWidth && bottomEdgeDistance <= effectHeight
8591

86-
if (clientY <= topBoundary) {
87-
hidePrompt()
92+
if (!withinEffectZone) {
93+
resetState()
8894
return
8995
}
9096

91-
if (rightEdgeDistance <= maxDistance) {
92-
const newIntensity = Math.max(0, (maxDistance - rightEdgeDistance) / maxDistance)
93-
intensity.set(newIntensity)
94-
95-
if (isShowPromptRef.current && rightEdgeDistance <= showedThreshold) {
96-
return
97-
}
98-
99-
const shouldShow = rightEdgeDistance <= threshold
100-
if (shouldShow !== isShowPromptRef.current) {
101-
isShowPromptRef.current = shouldShow
102-
setShowPrompt(shouldShow)
103-
}
104-
} else {
105-
hidePrompt()
97+
const normalizedX = 1 - Math.min(1, rightEdgeDistance / effectWidth)
98+
const normalizedY = 1 - Math.min(1, bottomEdgeDistance / effectHeight)
99+
const newIntensity = Math.max(normalizedX, normalizedY)
100+
intensity.set(newIntensity)
101+
102+
const withinActivation =
103+
rightEdgeDistance <= activationWidth && bottomEdgeDistance <= activationHeight
104+
const withinRelease =
105+
rightEdgeDistance <= releaseWidth && bottomEdgeDistance <= releaseHeight
106+
107+
if (withinActivation && !isShowPromptRef.current) {
108+
isShowPromptRef.current = true
109+
setShowPrompt(true)
110+
} else if (isShowPromptRef.current && !withinRelease) {
111+
isShowPromptRef.current = false
112+
setShowPrompt(false)
106113
}
107114
})
108115
}
@@ -112,7 +119,7 @@ const AIAmbientSidebar: React.FC<{ onExpand: () => void }> = ({ onExpand }) => {
112119
cancelAnimationFrame(frameRef.current)
113120
frameRef.current = null
114121
}
115-
hidePrompt()
122+
resetState()
116123
}
117124

118125
window.addEventListener("pointermove", handlePointerMove, { passive: true })
@@ -133,10 +140,10 @@ const AIAmbientSidebar: React.FC<{ onExpand: () => void }> = ({ onExpand }) => {
133140
return (
134141
<>
135142
{/* Multi-layer glass edge with depth */}
136-
<div className="pointer-events-none fixed right-0 top-0 z-40 h-full">
143+
<div className="pointer-events-none fixed inset-y-0 right-0 z-40">
137144
{/* Background layer - deepest */}
138145
<m.div
139-
className="ai-glass-layer-3 absolute right-0 top-0 h-full"
146+
className="ai-glass-layer-3 absolute inset-y-0 right-0 h-full"
140147
style={{
141148
width: layer3Width,
142149
opacity: layer3Opacity,
@@ -147,7 +154,7 @@ const AIAmbientSidebar: React.FC<{ onExpand: () => void }> = ({ onExpand }) => {
147154

148155
{/* Middle layer */}
149156
<m.div
150-
className="ai-glass-layer-2 absolute right-0 top-0 h-full"
157+
className="ai-glass-layer-2 absolute inset-y-0 right-0 h-full"
151158
style={{
152159
width: layer2Width,
153160
opacity: layer2Opacity,
@@ -159,7 +166,7 @@ const AIAmbientSidebar: React.FC<{ onExpand: () => void }> = ({ onExpand }) => {
159166

160167
{/* Front layer - most prominent */}
161168
<m.div
162-
className="ai-glass-layer-1 absolute right-0 top-0 h-full"
169+
className="ai-glass-layer-1 absolute inset-y-0 right-0 h-full"
163170
style={{
164171
width: layer1Width,
165172
opacity: layer1Opacity,
@@ -170,12 +177,13 @@ const AIAmbientSidebar: React.FC<{ onExpand: () => void }> = ({ onExpand }) => {
170177

171178
{/* Subtle ambient glow */}
172179
<m.div
173-
className="absolute right-0 top-1/2 size-32 -translate-y-1/2"
180+
className="absolute bottom-6 right-6 size-32"
174181
style={{
175182
opacity: glowOpacity,
176183
background: glowBackground,
177184
filter: "blur(30px)",
178185
x: glowX,
186+
y: glowY,
179187
}}
180188
/>
181189
</div>
@@ -187,7 +195,7 @@ const AIAmbientSidebar: React.FC<{ onExpand: () => void }> = ({ onExpand }) => {
187195
animate={{ opacity: 1, x: 0, scale: 1 }}
188196
exit={{ opacity: 0, x: 30, scale: 0.95 }}
189197
transition={Spring.presets.smooth}
190-
className="fixed bottom-12 right-6 z-50 flex flex-col items-end gap-3"
198+
className="fixed bottom-6 right-6 z-50 flex flex-col items-end gap-3"
191199
>
192200
{/* Unified glass card with integrated button */}
193201
<m.div

apps/desktop/layer/renderer/src/modules/entry-column/components/DateItem.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { ActionButton } from "@follow/components/ui/button/index.js"
22
import { FeedViewType } from "@follow/constants"
33
import { useIsListSubscription } from "@follow/store/subscription/hooks"
44
import { stopPropagation } from "@follow/utils/dom"
5-
import { cn } from "@follow/utils/utils"
5+
import { clsx, cn } from "@follow/utils/utils"
66
import type { FC, PropsWithChildren } from "react"
77
import { memo, useMemo, useRef, useState } from "react"
88
import { Trans } from "react-i18next"
@@ -15,6 +15,7 @@ import { getRouteParams, useRouteParams } from "~/hooks/biz/useRouteParams"
1515
import { useShowEntryDetailsColumn } from "~/hooks/biz/useShowEntryDetailsColumn"
1616

1717
import { markAllByRoute } from "../hooks/useMarkAll"
18+
import { readableContentMaxWidth } from "../styles"
1819

1920
interface DateItemInnerProps {
2021
date: Date
@@ -54,7 +55,7 @@ const UniversalDateItem = ({ date, className, isSticky }: Omit<DateItemProps, "v
5455

5556
return (
5657
<DateItemInner
57-
className={className}
58+
className={clsx(className, readableContentMaxWidth)}
5859
date={dateObj}
5960
startTime={startOfDay}
6061
endTime={endOfDay}

apps/desktop/layer/renderer/src/modules/entry-column/components/mark-all-button.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,12 @@ export const FlatMarkAllReadButton: FC<
143143
<button
144144
type="button"
145145
disabled={status === "done"}
146-
className={cn(styledButtonVariant({ variant: "ghost" }), className, buttonClassName)}
146+
className={cn(
147+
styledButtonVariant({ variant: "ghost" }),
148+
"rounded-none",
149+
className,
150+
buttonClassName,
151+
)}
147152
onClick={() => {
148153
markAllByRoute(getRouteParams(), filter)
149154
.then(() => setStatus("done"))

apps/desktop/layer/renderer/src/modules/entry-column/grid.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ const VirtualGridImpl: FC<
115115
return Array.from({ length: columnCount }).fill(width / columnCount) as number[]
116116
}, [containerWidth])
117117

118-
const isImageOnly = useUISettingKey("pictureViewImageOnly")
118+
const pictureViewImageOnly = useUISettingKey("pictureViewImageOnly")
119+
const isImageOnly = view === FeedViewType.Pictures && pictureViewImageOnly
119120

120121
// Calculate rows based on entries
121122
const rows = useMemo(() => {

apps/desktop/layer/renderer/src/modules/entry-column/layouts/EntryItemWrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ export const EntryItemWrapper: FC<
153153
to={navigationPath}
154154
className={cn(
155155
"relative block cursor-button overflow-visible duration-200 hover:bg-theme-item-hover",
156-
isWide ? "rounded-none @[650px]:rounded-md" : "",
156+
!isWide ? "rounded-none @[650px]:rounded-md" : "rounded-md",
157157
isAll && "!rounded-none",
158158
(isActive || isContextMenuOpen) && "!bg-theme-item-active",
159159
itemClassName,

apps/desktop/layer/renderer/src/modules/entry-column/templates/grid-item-template.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { TitleMarquee } from "@follow/components/ui/marquee/index.jsx"
2+
import { FeedViewType } from "@follow/constants"
23
import { useIsEntryStarred } from "@follow/store/collection/hooks"
34
import { useEntry, useHasEntry } from "@follow/store/entry/hooks"
45
import { useFeedById } from "@follow/store/feed/hooks"
@@ -9,6 +10,7 @@ import { useTranslation } from "react-i18next"
910

1011
import { useUISettingKey } from "~/atoms/settings/ui"
1112
import { useEntryIsRead } from "~/hooks/biz/useAsRead"
13+
import { useRouteParamsSelector } from "~/hooks/biz/useRouteParams"
1214
import { EntryTranslation } from "~/modules/entry-column/translation"
1315
import type { FeedIconEntry } from "~/modules/feed/feed-icon"
1416
import { FeedIcon } from "~/modules/feed/feed-icon"
@@ -80,7 +82,9 @@ export const GridItemFooter = ({
8082
const { t } = useTranslation("common")
8183

8284
const isImageOnly = useUISettingKey("pictureViewImageOnly")
83-
if (isImageOnly) return null
85+
const view = useRouteParamsSelector(({ view }) => view)
86+
const shouldHideFooter = view === FeedViewType.Pictures && isImageOnly
87+
if (shouldHideFooter) return null
8488

8589
if (!entry) return null
8690
return (

apps/desktop/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "Folo",
33
"type": "module",
4-
"version": "1.1.1",
4+
"version": "1.1.2",
55
"private": true,
66
"description": "Follow everything in one place",
77
"author": "Folo Team",

0 commit comments

Comments
 (0)