Fix profile server selection activation state
This commit is contained in:
@@ -199,11 +199,16 @@ export function createSubscriptionService(dependencies: SubscriptionServiceDepen
|
||||
if (!profile.servers.some((server) => server.id === serverId)) {
|
||||
throw new HarborError('SERVER_NOT_FOUND');
|
||||
}
|
||||
if (profile.desiredServerId === serverId) return mutationResult(profile);
|
||||
const selected = { ...profile, desiredServerId: serverId };
|
||||
if (profile.desiredServerId === serverId && state.desiredProfileId === profile.id) {
|
||||
return mutationResult(profile);
|
||||
}
|
||||
const selected = profile.desiredServerId === serverId
|
||||
? profile
|
||||
: { ...profile, desiredServerId: serverId };
|
||||
dependencies.state.update((current) => ({
|
||||
...current,
|
||||
profiles: replaceProfile(current, selected),
|
||||
desiredProfileId: profile.id,
|
||||
}));
|
||||
return mutationResult(selected);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const HARBOR_VERSIONS = Object.freeze({
|
||||
macClient: '0.23.11',
|
||||
gatewayClient: '0.24.11',
|
||||
gatewayBackend: '0.24.0',
|
||||
macClient: '0.24.0',
|
||||
gatewayClient: '0.25.0',
|
||||
gatewayBackend: '0.25.0',
|
||||
});
|
||||
|
||||
export interface ParsedVersion {
|
||||
|
||||
@@ -255,13 +255,6 @@ export function App() {
|
||||
`${profileId}:${serverId}`,
|
||||
profileId,
|
||||
)}
|
||||
onActivateProfile={(profileId: string) => run(
|
||||
'profileActivate',
|
||||
() => api.profiles.activate(profileId, revisionRef.current),
|
||||
'connection',
|
||||
profileId,
|
||||
profileId,
|
||||
)}
|
||||
onRefreshProfile={(profileId: string) => run(
|
||||
'profileRefresh',
|
||||
() => api.profiles.refresh(profileId, revisionRef.current),
|
||||
|
||||
@@ -105,7 +105,6 @@ interface ClientOverviewPageProps {
|
||||
error: UiError | null;
|
||||
onAddProfile: (label: string, url: string) => Promise<unknown>;
|
||||
onSelectProfileServer: (profileId: string, serverId: string) => Promise<unknown>;
|
||||
onActivateProfile: (profileId: string) => Promise<unknown>;
|
||||
onRefreshProfile: (profileId: string) => Promise<unknown>;
|
||||
onForgetProfile: (profileId: string, mode: 'delete' | 'stop-and-delete') => Promise<unknown>;
|
||||
onApply: (profileId: string, serverId: string) => Promise<unknown>;
|
||||
@@ -411,7 +410,6 @@ export function ClientOverviewPage({
|
||||
error,
|
||||
onAddProfile,
|
||||
onSelectProfileServer,
|
||||
onActivateProfile,
|
||||
onRefreshProfile,
|
||||
onForgetProfile,
|
||||
onApply,
|
||||
@@ -494,7 +492,6 @@ export function ClientOverviewPage({
|
||||
onAdd: onAddProfile,
|
||||
onRefresh: onRefreshProfile,
|
||||
onForget: onForgetProfile,
|
||||
onActivate: onActivateProfile,
|
||||
onDismissError,
|
||||
});
|
||||
const routingFeature = useRoutingFeature({
|
||||
@@ -553,7 +550,7 @@ export function ClientOverviewPage({
|
||||
}, []);
|
||||
|
||||
function selectServer(profile: ProfileSnapshot, serverId: string) {
|
||||
if (connected && !gatewayDirect && state.selection.appliedProfileId === profile.id) {
|
||||
if (connected && !gatewayDirect) {
|
||||
onApply(profile.id, serverId);
|
||||
return;
|
||||
}
|
||||
@@ -723,9 +720,9 @@ export function ClientOverviewPage({
|
||||
profileId={profile.id}
|
||||
pingServers={actions.pingServers}
|
||||
servers={profile.servers}
|
||||
selectedServerId={profile.desiredServerId}
|
||||
selectedServerId={pickerState.selectedServerId}
|
||||
disabled={serverApplyBlocked || pickerState.disabled}
|
||||
prompt={!profile.desiredServerId}
|
||||
prompt={!pickerState.selectedServerId}
|
||||
leaving={pickerState.leaving}
|
||||
revealVersion={pickerState.revealVersion}
|
||||
anchorServerId={pickerState.anchorServerId}
|
||||
|
||||
@@ -32,6 +32,7 @@ interface ServerPickerRenderState {
|
||||
leaving: boolean;
|
||||
revealVersion: number;
|
||||
anchorServerId: string;
|
||||
selectedServerId: string;
|
||||
}
|
||||
|
||||
interface SubscriptionFeatureOptions {
|
||||
@@ -45,7 +46,6 @@ interface SubscriptionFeatureOptions {
|
||||
onAdd: (label: string, url: string) => Promise<unknown>;
|
||||
onRefresh: (profileId: string) => Promise<unknown>;
|
||||
onForget: (profileId: string, mode: 'delete' | 'stop-and-delete') => Promise<unknown>;
|
||||
onActivate: (profileId: string) => Promise<unknown>;
|
||||
onDismissError: () => void;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,6 @@ export function useSubscriptionFeature({
|
||||
onAdd,
|
||||
onRefresh,
|
||||
onForget,
|
||||
onActivate,
|
||||
onDismissError,
|
||||
}: SubscriptionFeatureOptions) {
|
||||
const [open, setOpen] = useState(false);
|
||||
@@ -281,7 +280,6 @@ export function useSubscriptionFeature({
|
||||
addBlocked: operationBlocked(operations, 'profileAdd'),
|
||||
refreshBlocked: operationBlocked(operations, 'profileRefresh'),
|
||||
deleteBlocked: operationBlocked(operations, 'profileDelete'),
|
||||
activateBlocked: operationBlocked(operations, 'profileActivate'),
|
||||
toggle: () => setOpen((current) => !current),
|
||||
close: () => setOpen(false),
|
||||
showAdd,
|
||||
@@ -296,7 +294,6 @@ export function useSubscriptionFeature({
|
||||
cancelDelete: () => setDeleteId(''),
|
||||
confirmDelete,
|
||||
refresh,
|
||||
onActivate,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -394,8 +391,9 @@ function ProfileGroup({
|
||||
const refreshing = feature.refreshingIds.includes(profile.id)
|
||||
|| feature.operations.profileRefresh?.target === profile.id;
|
||||
const controlsBlocked = operationBlocked(feature.operations, 'profileSelect');
|
||||
const selectedServer = profileServer(profile, profile.desiredServerId);
|
||||
const visibleServerId = applied ? feature.selection.appliedServerId : profile.desiredServerId;
|
||||
const visibleServerId = applied
|
||||
? feature.selection.appliedServerId
|
||||
: desired ? profile.desiredServerId : '';
|
||||
const visibleServer = profileServer(profile, visibleServerId)
|
||||
|| (applied && feature.selection.appliedServerSnapshot?.id === visibleServerId
|
||||
? feature.selection.appliedServerSnapshot
|
||||
@@ -403,7 +401,6 @@ function ProfileGroup({
|
||||
const visibleServerLocation = [visibleServer?.city, visibleServer?.country]
|
||||
.filter((value): value is string => typeof value === 'string' && Boolean(value))
|
||||
.join(' · ');
|
||||
const canActivate = !applied && feature.selection.desiredProfileId !== profile.id;
|
||||
const localStatus = profileError?.message || (profile.subscription.status === 'stale'
|
||||
? `Последнее обновление не удалось. Данные от ${profile.subscription.fetchedAt
|
||||
? new Date(profile.subscription.fetchedAt).toLocaleString('ru-RU', { dateStyle: 'short', timeStyle: 'short' })
|
||||
@@ -431,12 +428,7 @@ function ProfileGroup({
|
||||
<small>{profileDetails}</small>
|
||||
</span>
|
||||
</button>
|
||||
{canActivate ? <button
|
||||
className="client-profile-activate"
|
||||
type="button"
|
||||
disabled={feature.activateBlocked || !selectedServer}
|
||||
onClick={() => feature.onActivate(profile.id)}
|
||||
>Сделать активной</button> : <ProfileUsage profile={profile} />}
|
||||
{(applied || desired) && <ProfileUsage profile={profile} />}
|
||||
<button
|
||||
className={`client-profile-refresh${refreshing ? ' is-refreshing' : ''}`}
|
||||
type="button"
|
||||
@@ -483,12 +475,13 @@ function ProfileGroup({
|
||||
inert={!expanded ? true : undefined}
|
||||
>
|
||||
<div className="client-profile-body-inner">
|
||||
{!profile.desiredServerId && <p className="client-profile-server-hint">Выберите сервер этой подписки</p>}
|
||||
{!visibleServerId && <p className="client-profile-server-hint">Выберите сервер этой подписки</p>}
|
||||
{renderServerPicker(profile, {
|
||||
disabled: controlsBlocked,
|
||||
leaving: false,
|
||||
revealVersion: feature.revealVersions[profile.id] || 0,
|
||||
anchorServerId: visibleServer?.id || '',
|
||||
selectedServerId: visibleServerId,
|
||||
})}
|
||||
</div>
|
||||
</div>}
|
||||
|
||||
@@ -149,6 +149,8 @@
|
||||
}
|
||||
|
||||
.client-profile-usage {
|
||||
grid-column: 2;
|
||||
justify-self: end;
|
||||
max-width: 126px;
|
||||
overflow: hidden;
|
||||
color: var(--client-muted);
|
||||
@@ -188,6 +190,14 @@
|
||||
transition: transform 600ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.client-profile-refresh {
|
||||
grid-column: 3;
|
||||
}
|
||||
|
||||
.client-profile-delete {
|
||||
grid-column: 4;
|
||||
}
|
||||
|
||||
.client-profile-delete-lid {
|
||||
transform-origin: center 7px;
|
||||
transition: transform 260ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||
@@ -327,7 +337,6 @@
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.client-profile-activate,
|
||||
.client-profile-add-trigger {
|
||||
min-height: 36px;
|
||||
padding: 0;
|
||||
@@ -365,18 +374,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.client-profile-activate {
|
||||
font: var(--type-micro);
|
||||
letter-spacing: var(--type-micro-tracking);
|
||||
text-transform: var(--type-micro-transform);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.client-profile-activate:disabled {
|
||||
opacity: 0.35;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.client-profile-add-trigger {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
|
||||
Reference in New Issue
Block a user