diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json index d7ee5136..c1325058 100644 --- a/src/renderer/src/i18n/locales/en.json +++ b/src/renderer/src/i18n/locales/en.json @@ -123,6 +123,14 @@ "failedToRegisterNewDevice": "Failed to register new device. Please try again later." } }, + "modals": { + "xAccountMode": { + "title": "Do you still have access to your X account?", + "description": "If you can't login to your X account (you deleted it, or you were permanently suspended), but you have an X archive, add this account in Archive Only mode. You won't be able to delete data in this mode, but you can migrate your data to Bluesky.", + "loginButton": "I Can Login to X", + "archiveOnlyButton": "I Can't Login, Use Archive Only Mode" + } + }, "errorReport": { "title": "Submit an error report", "errorsOccurred": "{count} errors occured", @@ -346,8 +354,7 @@ "platform": { "u2fNotice": "If you use a U2F security key (like a Yubikey) for 2FA, press it when you see a white screen.", "u2fNoticeFacebook": "If you use a U2F security key (like a Yubikey) for 2FA, press it when prompted.", - "readMore": "Read more", - "importArchiveOnly": "Import Archive Only (for deleted accounts with an archive)" + "readMore": "Read more" }, "finished": { "viewBlueskyProfile": "View Bluesky Profile", diff --git a/src/renderer/src/modals/XAccountModeModal.vue b/src/renderer/src/modals/XAccountModeModal.vue new file mode 100644 index 00000000..d0d864cd --- /dev/null +++ b/src/renderer/src/modals/XAccountModeModal.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/src/renderer/src/views/PlatformView.vue b/src/renderer/src/views/PlatformView.vue index c9c4ef7d..bd884614 100644 --- a/src/renderer/src/views/PlatformView.vue +++ b/src/renderer/src/views/PlatformView.vue @@ -76,9 +76,6 @@ const emit = defineEmits<{ finishedRunAgainClicked: []; updateUserPremium: []; - // Archive only (conditional on feature flag) - archiveOnlyClicked: []; - // Job control events onPause: []; onResume: []; @@ -181,20 +178,6 @@ const currentJobsLength = computed(() => props.currentJobs.length); >.

- -
- - - -
- diff --git a/src/renderer/src/views/x/XView.vue b/src/renderer/src/views/x/XView.vue index 3b09d765..0f5080fb 100644 --- a/src/renderer/src/views/x/XView.vue +++ b/src/renderer/src/views/x/XView.vue @@ -5,7 +5,7 @@ * Thin wrapper around PlatformView that handles X-specific logic: * - XViewModel instantiation * - X-specific state (rateLimitInfo, failure states, mediaPath) - * - X-specific methods (archiveOnlyClicked, startJobs, etc.) + * - X-specific methods (startJobs, etc.) * - X-specific event handlers */ @@ -49,6 +49,7 @@ import { usePlatformView } from "../../composables/usePlatformView"; import { getPlatformConfig } from "../../config/platforms"; import PlatformView from "../PlatformView.vue"; import XProgressComponent from "./components/XProgressComponent.vue"; +import XAccountModeModal from "../../modals/XAccountModeModal.vue"; // Get the global emitter const vueInstance = getCurrentInstance(); @@ -68,6 +69,7 @@ const failureStateIndexTweets_FailedToRetryAfterRateLimit = ref(false); const failureStateIndexLikes_FailedToRetryAfterRateLimit = ref(false); const rateLimitInfo = ref(null); const mediaPath = ref(""); +const showAccountModeModal = ref(false); // The X view model const model = ref(new XViewModel(props.account, emitter)); @@ -141,11 +143,6 @@ watch( ); // X-specific methods -const archiveOnlyClicked = async () => { - model.value.cancelWaitForURL = true; - await setState(State.WizardArchiveOnly.toString()); -}; - const onAutomationErrorRetry = async () => { console.log("Retrying automation after error"); @@ -322,6 +319,47 @@ const debugModeDisable = async () => { model.value.state = State.WizardPrestart; }; +// Account mode modal handlers +const handleAccountModeModalLogin = async () => { + showAccountModeModal.value = false; + await nextTick(); // Wait for PlatformView to render + + // Initialize the platform view now that it's rendered + if ( + platformViewRef.value?.webviewComponent !== null && + platformViewRef.value?.webviewComponent !== undefined + ) { + const webview = platformViewRef.value.webviewComponent as WebviewTag; + await initializePlatformView(webview); + } + + model.value.state = State.Login; + await startStateLoop(); +}; + +const handleAccountModeModalArchiveOnly = async () => { + showAccountModeModal.value = false; + await nextTick(); // Wait for PlatformView to render + + // Initialize the platform view now that it's rendered + if ( + platformViewRef.value?.webviewComponent !== null && + platformViewRef.value?.webviewComponent !== undefined + ) { + const webview = platformViewRef.value.webviewComponent as WebviewTag; + await initializePlatformView(webview); + } + + await window.electron.X.initArchiveOnlyMode(props.account.id); + await updateAccount(); + model.value.state = State.WizardArchiveOnly; + await startStateLoop(); +}; + +const handleAccountModeModalHide = () => { + showAccountModeModal.value = false; +}; + // Lifecycle onMounted(async () => { setupAuthListeners(); @@ -332,7 +370,16 @@ onMounted(async () => { // Wait for child components to mount await nextTick(); - if ( + // Check if we need to show the account mode modal (new account with no username) + const shouldShowModal = + props.account.xAccount !== null && + !props.account.xAccount.username && + !localStorage.getItem(`account-${props.account.id}-state`); + + if (shouldShowModal) { + showAccountModeModal.value = true; + // Don't initialize platform view yet - it will be done in the modal handlers + } else if ( platformViewRef.value?.webviewComponent !== null && platformViewRef.value?.webviewComponent !== undefined ) { @@ -385,6 +432,7 @@ onUnmounted(async () => { + + +