Add Windows save instructions UI and fix URL #296

- Add Windows instruction dialog when saving scripts for Windows.
- Fix incorrect macOS download URL given for Linux instructions.
- Refactor UI rendering, eleminating the use of `v-html` and JavaScript
  variables to hold HTML code.
This commit is contained in:
undergroundwires
2024-01-15 22:38:39 +01:00
parent e09db0f1bd
commit 756c736e21
24 changed files with 705 additions and 537 deletions

View File

@@ -0,0 +1,76 @@
<template>
<span class="code-wrapper">
<span class="dollar">$</span>
<code ref="codeElement"><slot /></code>
<div class="copy-action-container">
<TooltipWrapper>
<FlatButton icon="copy" @click="copyCode" />
<template #tooltip>
Copy
</template>
</TooltipWrapper>
</div>
</span>
</template>
<script lang="ts">
import { defineComponent, shallowRef } from 'vue';
import TooltipWrapper from '@/presentation/components/Shared/TooltipWrapper.vue';
import { injectKey } from '@/presentation/injectionSymbols';
import FlatButton from '@/presentation/components/Shared/FlatButton.vue';
export default defineComponent({
components: {
TooltipWrapper,
FlatButton,
},
setup() {
const { copyText } = injectKey((keys) => keys.useClipboard);
const codeElementRef = shallowRef<HTMLElement | undefined>();
async function copyCode() {
const element = codeElementRef.value;
if (!element) {
throw new Error('Code element could not be found.');
}
const code = element.textContent;
if (!code) {
throw new Error('Code element does not contain any text.');
}
await copyText(code);
}
return {
copyCode,
codeElement: codeElementRef,
};
},
});
</script>
<style scoped lang="scss">
@use "@/presentation/assets/styles/main" as *;
.code-wrapper {
display: inline-flex;
white-space: nowrap;
justify-content: space-between;
font-family: $font-normal;
background-color: $color-primary-darker;
color: $color-on-primary;
align-items: center;
padding: 0.2rem;
.dollar {
margin-right: 0.5rem;
font-size: 0.8rem;
user-select: none;
}
.copy-action-container {
margin-left: 1rem;
}
code {
font-size: 1rem;
}
}
</style>

View File

@@ -0,0 +1,19 @@
<template>
<li class="step">
<slot />
</li>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'InstructionSteps', // Define component name for empty component for Vue build and ESLint compatibility.
});
</script>
<style scoped lang="scss">
.step {
margin: 10px 0;
}
</style>

View File

@@ -0,0 +1,13 @@
<template>
<ol>
<slot />
</ol>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'InstructionSteps', // Define component name for empty component for Vue build and ESLint compatibility.
});
</script>

View File

@@ -0,0 +1,50 @@
<template>
<component
:is="component"
v-if="component"
:filename="filename"
/>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
import { injectKey } from '@/presentation/injectionSymbols';
import { OperatingSystem } from '@/domain/OperatingSystem';
import MacOsInstructions from './Platforms/MacOsInstructions.vue';
import LinuxInstructions from './Platforms/LinuxInstructions.vue';
import WindowsInstructions from './Platforms/WindowsInstructions.vue';
import type { Component } from 'vue';
export default defineComponent({
props: {
filename: {
type: String,
required: true,
},
},
setup() {
const { currentState } = injectKey((keys) => keys.useCollectionState);
const component = computed<Component>(() => getInstructionsComponent(
currentState.value.collection.os,
));
return {
component,
};
},
});
function getInstructionsComponent(operatingSystem: OperatingSystem): Component {
switch (operatingSystem) {
case OperatingSystem.macOS:
return MacOsInstructions;
case OperatingSystem.Linux:
return LinuxInstructions;
case OperatingSystem.Windows:
return WindowsInstructions;
default:
throw new Error(`No instructions for the operating system: ${OperatingSystem[operatingSystem]}`);
}
}
</script>

View File

@@ -0,0 +1,155 @@
<template>
<InstructionSteps>
<InstructionStep>
Download the file.
<InfoTooltip>
<p>
You should have already been prompted to save the script file.
</p>
<p>
If this was not the case or you did not save the script when prompted,
please try to download your script file again.
</p>
</InfoTooltip>
</InstructionStep>
<InstructionStep>
Open terminal.
<InfoTooltip>
<p>
Opening terminal changes based on the distro you run.
</p>
<p>
You may search for "Terminal" in your application launcher to find it.
</p>
<p>
Alternatively use terminal shortcut for your distro if it has one by default:
<ul>
<li>
<code>Ctrl-Alt-T</code>:
Ubuntu, CentOS, Linux Mint, Elementary OS, ubermix, Kali
</li>
<li>
<code>Super-T</code>: Pop!_OS
</li>
<li>
<code>Alt-T</code>: Parrot OS
</li>
<li>
<code>Ctrl-Alt-Insert</code>: Bodhi Linux
</li>
</ul>
</p>
</InfoTooltip>
</InstructionStep>
<InstructionStep>
<p>
Navigate to the folder where you downloaded the file e.g.:
</p>
<p>
<CopyableCommand>
cd ~/Downloads
</CopyableCommand>
<InfoTooltip>
<p>
Press on <code>enter/return</code> key after running the command.
</p>
<p>
If the file is not downloaded on Downloads folder,
change <code>Downloads</code> to path where the file is downloaded.
</p>
<p>
This command means:
<ul>
<li><code>cd</code> will change the current folder.</li>
<li><code>~</code> is the user home directory.</li>
</ul>
</p>
</InfoTooltip>
</p>
</InstructionStep>
<InstructionStep>
<p>
Give the file execute permissions:
</p>
<p>
<CopyableCommand>
chmod +x {{ filename }}
</CopyableCommand>
<InfoTooltip>
<p>
Press on <code>enter/return</code> key after running the command.
</p>
<p>
It will make the file executable.
</p>
<p>
If you use desktop environment you can alternatively (instead of running the command):
<ol>
<li>Locate the file using your file manager.</li>
<li>Right click on the file, select "Properties".</li>
<li>Go to "Permissions" and check "Allow executing file as program".</li>
</ol>
</p>
<p>
These GUI steps and name of options may change depending on your file manager.'
</p>
</InfoTooltip>
</p>
</InstructionStep>
<InstructionStep>
<p>
Execute the file:
</p>
<p>
<CopyableCommand>
./{{ filename }}
</CopyableCommand>
<InfoTooltip>
If you have desktop environment, instead of running this command you can alternatively:
<ol>
<li>Locate the file using your file manager.</li>
<li>Right click on the file, select "Run as program".</li>
</ol>
</InfoTooltip>
</p>
</InstructionStep>
<InstructionStep>
If asked, enter your administrator password.
<InfoTooltip>
<p>
As you type, your password will be hidden but the keys are still
registered, so keep typing.
</p>
<p>
Press on <code>enter/return</code> key after typing your password.
</p>
<p>
Administrator privileges are required to configure OS.
</p>
</InfoTooltip>
</InstructionStep>
</InstructionSteps>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import InstructionSteps from '../InstructionSteps.vue';
import InstructionStep from '../InstructionStep.vue';
import InfoTooltip from '../../InfoTooltip.vue';
import CopyableCommand from '../CopyableCommand.vue';
export default defineComponent({
components: {
CopyableCommand,
InfoTooltip,
InstructionSteps,
InstructionStep,
},
props: {
filename: {
type: String,
required: true,
},
},
});
</script>

View File

@@ -0,0 +1,117 @@
<template>
<InstructionSteps>
<InstructionStep>
Download the file.
<InfoTooltip>
<p>
You should have already been prompted to save the script file.
</p>
<p>
If this was not the case or you did not save the script when prompted,
please try to download your script file again.
</p>
</InfoTooltip>
</InstructionStep>
<InstructionStep>
Open terminal.
<InfoTooltip>
Type Terminal into Spotlight or open it from the Applications -> Utilities folder.
</InfoTooltip>
</InstructionStep>
<InstructionStep>
<p>
Navigate to the folder where you downloaded the file e.g.:
</p>
<p>
<CopyableCommand>
cd ~/Downloads
</CopyableCommand>
<InfoTooltip>
<p>
Press on <code>enter/return</code> key after running the command.
</p>
<p>
If the file is not downloaded on Downloads folder,
change <code>Downloads</code> to path where the file is downloaded.
</p>
<p>
This command means:
<ul>
<li><code>cd</code> will change the current folder.</li>
<li><code>~</code> is the user home directory.</li>
</ul>
</p>
</InfoTooltip>
</p>
</InstructionStep>
<InstructionStep>
<p>
Give the file execute permissions:
</p>
<p>
<CopyableCommand>
chmod +x {{ filename }}
</CopyableCommand>
<InfoTooltip>
<p>
Press on <code>enter/return</code> key after running the command.
</p>
<p>
It will make the file executable.
</p>
</InfoTooltip>
</p>
</InstructionStep>
<InstructionStep>
<p>
Execute the file:
</p>
<p>
<CopyableCommand>
./{{ filename }}
</CopyableCommand>
<InfoTooltip>
Alternatively you can locate the file in <strong>Finder</strong> and double click on it.
</InfoTooltip>
</p>
</InstructionStep>
<InstructionStep>
If asked, enter your administrator password.
<InfoTooltip>
<p>
As you type, your password will be hidden but the keys are
still registered, so keep typing.
</p>
<p>
Press on <code>enter/return</code> key after typing your password.
</p>
<p>
Administrator privileges are required to configure OS.
</p>
</InfoTooltip>
</InstructionStep>
</InstructionSteps>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import InstructionSteps from '../InstructionSteps.vue';
import InstructionStep from '../InstructionStep.vue';
import InfoTooltip from '../../InfoTooltip.vue';
import CopyableCommand from '../CopyableCommand.vue';
export default defineComponent({
components: {
CopyableCommand,
InfoTooltip,
InstructionSteps,
InstructionStep,
},
props: {
filename: {
type: String,
required: true,
},
},
});
</script>

View File

@@ -0,0 +1,154 @@
<template>
<InstructionSteps>
<InstructionStep>
Download the file.
<InfoTooltip>
<p>If a save prompt doesn't appear, try downloading the script again.</p>
</InfoTooltip>
</InstructionStep>
<InstructionStep>
If warned by your browser, keep the file.
<InfoTooltip>
<!--
Tests (15/01/2023):
- Edge (Defender activated): "filename isn't commonly downloaded..."
- Chrome: No warning, downloads directly.
- Firefox: No warning, downloads directly.
-->
<p>
Browsers may warn you when downloading scripts.
</p>
<p>
privacy.sexy scripts are verified to be safe and are dedicated to securing your privacy.
</p>
<p>
In <strong>Edge</strong>:
<ol>
<li>Select <strong>Keep</strong> from the downloads section.</li>
<li>Click <strong>Show more</strong> on the next warning.</li>
<li>Select <strong>Keep anyway</strong>.</li>
</ol>
</p>
<p>
For <strong>Firefox</strong> and <strong>Chrome</strong>, typically no additional
action is needed.
</p>
</InfoTooltip>
</InstructionStep>
<InstructionStep>
If your antivirus (e.g., Defender) alerts you, address the warning.
<InfoTooltip>
<!--
Tests (15/01/2023):
- Edge (Defender activated): "Couldn't download - Virus detected"
- Chrome: "Virus detected"
- Firefox: Does not trigger false-positive on Defender somehow.
-->
<p>
Depending on the script, antivirus software may incorrectly flag the download as a threat.
</p>
<p>
These false positives are common for scripts that modify system settings.
</p>
<p>
To handle false warnings in Microsoft Defender:
<ol>
<li>Open <strong>Virus & threat protection</strong> from the Start menu.</li>
<li>
Locate the event in <strong>Protection history</strong>
that pertains to the script.
</li>
<li>In the event details, select <strong>Actions</strong> > <strong>Allow</strong>.</li>
<li>If the script was deleted, please re-download it.</li>
</ol>
</p>
<blockquote>
<strong>Caution:</strong> For your security, remember to:
<ul>
<li>Only allow scripts from trusted sources.</li>
<li>Avoid broad exclusions in your antivirus settings.</li>
<li>Keep real-time protection enabled whenever possible.</li>
</ul>
</blockquote>
</InfoTooltip>
</InstructionStep>
<InstructionStep>
<!--
Tests (15/01/2023):
- Edge (Defender activated): No prompts
- Chrome: No prompts
- Firefox: "filename is executable file. Executable files may contain..?" OK/Cancel
-->
Open the downloaded file.
<InfoTooltip>
<p>
Confirm any browser prompts to open the file.
</p>
<p>
This standard security measure ensures that you are aware of the script execution.
</p>
<p>
<strong>Firefox</strong> users, click <strong>OK</strong> to acknowledge the
executable file warning.
</p>
<p>
<strong>Edge</strong> and <strong>Chrome</strong> users usually will not
encounter additional prompts.
</p>
</InfoTooltip>
</InstructionStep>
<InstructionStep>
If prompted, confirm SmartScreen warnings.
<InfoTooltip>
<p>
Windows SmartScreen might display a cautionary message.
</p>
<p>
This happens since privacy.sexy scripts are not recognized
by Microsoft's certification process.
</p>
<p>
<ol>
<li>Select <strong>More info</strong>.</li>
<li>Select <strong>Run anyway</strong>.</li>
</ol>
</p>
</InfoTooltip>
</InstructionStep>
<InstructionStep>
If administrative permissions are requested, grant them.
<InfoTooltip>
<p>
The script may request administrative rights to apply changes.
</p>
<p>
This is necessary for the script to apply the intended privacy settings.
</p>
<p>
Click <strong>Yes</strong> to authorize and run the script.
</p>
</InfoTooltip>
</InstructionStep>
</InstructionSteps>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import InstructionSteps from '../InstructionSteps.vue';
import InstructionStep from '../InstructionStep.vue';
import InfoTooltip from '../../InfoTooltip.vue';
export default defineComponent({
components: {
InfoTooltip,
InstructionSteps,
InstructionStep,
},
props: {
filename: {
type: String,
required: true,
},
},
});
</script>