modals (WIP); mirc to clipboard

This commit is contained in:
Hugh Bord 2021-04-24 10:20:11 +10:00
parent 2edcfc069f
commit 71ac1e288a
11 changed files with 1555 additions and 164 deletions

View File

@ -4,6 +4,11 @@ ASCIIBIRD DEVELOPMENT - TAKING FLIGHT
# FOCUSING ON NOW
* Modals
* Export to clipboard
* Encodings
* Toolbar stuff / Brush Size
* Context Menus (right click menu) - we started this
* Keyboard shortcuts
@ -55,6 +60,8 @@ ASCIIBIRD DEVELOPMENT - TAKING FLIGHT
* https://modern.ircdocs.horse/formatting.html#color
* https://www.mirc.com/colors.html
* https://github.com/polygonplanet/encoding.js/
## Project setup
```
yarn

View File

@ -14,6 +14,7 @@
"@fortawesome/vue-fontawesome": "^2.0.2",
"pako": "^2.0.3",
"vue": "^2.6.11",
"vue-clipboard2": "^0.3.1",
"vue-draggable-resizable": "^2.3.0",
"vue-tailwind": "^2.0.0",
"vuex": "^3.4.0",

View File

@ -1,59 +1,31 @@
<template>
<div id="app">
<t-modal
name="create-ascii-modal"
header="Create new ASCII"
:clickToClose="false"
:escToClose="false"
@before-closed="closeNewASCII"
>
Width
<t-input
type="number"
name="width"
v-model="forms.createAscii.width"
min="1"
/>
Height
<t-input
type="number"
name="height"
v-model="forms.createAscii.height"
min="1"
/>
Title
<t-input
type="text"
name="title"
v-model="forms.createAscii.title"
max="128"
/>
<template v-slot:footer>
<div
class="flex justify-between"
@click="$modal.hide('create-ascii-modal')"
>
<t-button type="button"> Cancel </t-button>
<t-button type="button" @click="createNewASCII()"> Ok </t-button>
</div>
</template>
</t-modal>
<NewAscii :showNewAsciiModal="showNewAsciiModal" />
<context-menu :display="showContextMenu" ref="menu">
<ul>
<li @click="createClick()" class="ml-1" @contextmenu.prevent>New ASCII</li>
<li
@click="showNewAsciiModal = !showNewAsciiModal"
class="ml-1"
@contextmenu.prevent
>
New ASCII
</li>
<li @click="clearCache()" class="ml-1">Clear and Refresh</li>
<li @click="startImport('mirc')" class="ml-1">Import mIRC</li>
<li
@click="exportMirc()"
@click="exportMirc('file')"
class="ml-1"
v-if="this.$store.getters.asciibirdMeta.length"
>
Export ASCII to mIRC
Export mIRC to File
</li>
<li
class="ml-1"
@click="exportMirc('clipboard')"
v-if="this.$store.getters.asciibirdMeta.length"
>
Export mIRC to Clipboard
</li>
<li
@click="exportAsciibirdState()"
@ -127,20 +99,29 @@ import Editor from "./views/Editor.vue";
import CharPicker from "./components/parts/CharPicker.vue";
import ColourPicker from "./components/parts/ColourPicker.vue";
import ContextMenu from "./components/parts/ContextMenu.vue";
import NewAscii from "./components/modals/NewAscii.vue";
// import AsciiCursor from './components/parts/AsciiCursor.vue';
// import pako from 'pako';
export default {
async created() {
// Load from irc watch if present in the URL bar
// const asciiUrl = new URL(location.href).searchParams.get("ircwatch");
// if (asciiUrl) {
// const res = await fetch(`https://irc.watch/ascii/txt/${asciiUrl}`);
// const asciiData = await res.text();
// this.mircAsciiImport(asciiData, asciiUrl);
// window.location.href = "/";
// }
console.log(window.asciiList);
const asciiUrl = new URL(location.href).searchParams.get("ascii");
if (asciiUrl) {
const res = await fetch(`https://ascii.jewbird.live/${asciiUrl}`, {
method: "GET",
headers: {
Accept: "text/plain",
},
});
const asciiData = await res.text();
console.log({ asciiData, asciiUrl });
this.mircAsciiImport(asciiData, asciiUrl);
window.location.href = "/";
}
},
components: {
Toolbar,
@ -148,17 +129,12 @@ export default {
Editor,
CharPicker,
ColourPicker,
ContextMenu
ContextMenu,
NewAscii,
},
name: "Dashboard",
data: () => ({
forms: {
createAscii: {
width: 5,
height: 5,
title: "ascii",
},
},
showNewAsciiModal: false,
currentTab: 1,
canvasX: null,
canvasY: null,
@ -326,8 +302,8 @@ export default {
blockWidth: 8 * this.$store.getters.blockSizeMultiplier,
blockHeight: 13 * this.$store.getters.blockSizeMultiplier,
blocks: this.create2DArray(asciiImport.split("\n").length),
x: 247, // the dragable ascii canvas x
y: 24, // the dragable ascii canvas y
x: 8 * 35, // the dragable ascii canvas x
y: 13 * 2, // the dragable ascii canvas y
};
// Turn the entire ascii string into an array
@ -368,7 +344,7 @@ export default {
// trimmed it will trim the entire ascii!
if (!finalAscii.width) {
finalAscii.width =
asciiImport.split("\n")[0].length - 1 - widthOfColCodes; // minus \n for the proper width
asciiImport.split("\n")[0].length - widthOfColCodes; // minus \n for the proper width
}
// Resets the X value
@ -542,7 +518,7 @@ export default {
console.log(err);
}
},
exportMirc() {
exportMirc(type) {
const { currentAscii } = this.$store.getters;
const output = [];
let curBlock = null;
@ -589,7 +565,23 @@ export default {
currentAscii.title.slice(currentAscii.title.length - 3) === "txt"
? currentAscii.title
: `${currentAscii.title}.txt`;
this.downloadToFile(output.join(""), filename, "text/plain");
switch (type) {
case "clipboard":
this.$copyText(output.join("")).then(function (e) {
alert('Copied')
console.log(e)
}, function (e) {
alert('Can not copy')
console.log(e)
})
break;
default:
case "file":
this.downloadToFile(output.join(""), filename, "text/plain");
break;
}
},
downloadToFile(content, filename, contentType) {
const downloadToFile = (content, filename, contentType) => {
@ -605,10 +597,6 @@ export default {
return downloadToFile(content, filename, contentType);
},
createClick() {
this.forms.createAscii.title = `New ASCII ${this.$store.getters.asciibirdMeta.length}`;
this.$modal.show("create-ascii-modal");
},
changeTab(key, value) {
// Update the tab index in vuex store
this.currentTab = key;
@ -618,38 +606,7 @@ export default {
localStorage.clear();
window.location.href = "/";
},
createNewASCII() {
const payload = {
title: this.forms.createAscii.title,
key: this.$store.getters.asciibirdMeta.length,
width: this.forms.createAscii.width,
height: this.forms.createAscii.height,
blockWidth: 8,
blockHeight: 13,
x: 247, // the dragable ascii canvas x
y: 24, // the dragable ascii canvas y
blocks: this.create2DArray(this.forms.createAscii.height),
};
// Push all the default ASCII blocks
for (let x = 0; x < payload.width; x++) {
for (let y = 0; y < payload.height; y++) {
payload.blocks[y].push({
bg: null,
fg: null,
char: null,
});
}
}
this.$store.commit("newAsciibirdMeta", payload);
this.$modal.hide("create-ascii-modal");
},
closeNewASCII({ params, cancel }) {
this.forms.createAscii.width = 5;
this.forms.createAscii.height = 5;
this.forms.createAscii.title = "New ASCII";
},
create2DArray(rows) {
const arr = [];

1
src/ascii.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -2,37 +2,46 @@
<div>
<vue-draggable-resizable
@dragstop="onDragStop"
:grid="[currentAscii.blockWidth, currentAscii.blockHeight]"
:min-width="8 * 100"
:max-width="8 * 150"
:min-height="13 * 4"
:max-height="13 * 4"
style="z-index: 5;"
:min-width="200"
:max-width="500"
:min-height="200"
:max-height="500"
:x="$store.getters.getDebugPanelState.x"
:y="$store.getters.getDebugPanelState.y"
:w="debugPanelState.w"
:h="debugPanelState.h"
:x="debugPanelState.x"
:y="debugPanelState.y"
>
<t-card style="height: 100%;">
<p v-html="`Tool: ${getToolName}`"></p>
<p v-html="`FgColour: ${$store.getters.getFgColour}`"></p>
<p v-html="`BgColor: ${$store.getters.getBgColour}`"></p>
<p v-html="`Char: ${$store.getters.getToolbarState.selectedChar}`"></p>
<span class="ml-5" v-html="`Tool: ${getToolName}`"></span>
<span class="ml-5" v-html="`FgColour: ${$store.getters.getFgColour}`"></span>
<span class="ml-5" v-html="`BgColor: ${$store.getters.getBgColour}`"></span>
<span class="ml-5" v-html="`Char: ${$store.getters.getToolbarState.selectedChar}`"></span>
<p v-html="`canvasX: ${canvasX}`"></p>
<p v-html="`canvasY: ${canvasY}`"></p>
<span class="ml-5" v-html="`canvasX: ${canvasX}`"></span>
<span class="ml-5" v-html="`canvasY: ${canvasY}`"></span>
</t-card>
</vue-draggable-resizable>
</div>
</template>
<script>
export default {
created() {},
created() {
this.panel.x = this.debugPanelState.x
this.panel.y = this.debugPanelState.y
this.panel.w = this.debugPanelState.w
this.panel.h = this.debugPanelState.h
},
name: "DebugPanel",
props: ["canvasX", "canvasY"],
data: () => ({
floating: {
width: 0,
height: 0,
panel: {
w: 0,
h: 0,
x: 100,
y: 100,
},
@ -41,21 +50,29 @@ export default {
computed: {
getToolName() {
return this.$store.getters.getToolbarIcons[this.$store.getters.getCurrentTool] ? this.$store.getters.getToolbarIcons[this.$store.getters.getCurrentTool].name : 'none'
}
},
debugPanelState() {
return this.$store.getters.getDebugPanelState
},
currentAscii() {
return this.$store.getters.currentAscii;
},
},
watch: {},
methods: {
onResize(x, y, width, height) {
this.floating.x = x;
this.floating.y = y;
this.floating.width = width;
this.floating.height = height;
onResize(x, y, w, h) {
this.panel.x = x;
this.panel.y = y;
this.panel.w = w;
this.panel.h = h;
this.$store.commit("changeDebugPanelState", this.panel)
},
onDragStop(x, y) {
this.floating.x = x;
this.floating.y = y;
this.panel.x = x;
this.panel.y = y;
this.$store.commit("changeDebugPanelState", {x: x, y: y})
this.$store.commit("changeDebugPanelState", this.panel)
},
},
};

View File

@ -2,23 +2,22 @@
<div>
<vue-draggable-resizable
@dragstop="onDragStop"
:grid="[
$store.getters.currentAscii.blockHeight,
$store.getters.currentAscii.blockWidth,
]"
:grid="[currentAscii.blockWidth, currentAscii.blockHeight]"
style="z-index: 5;"
:min-width="200"
:max-width="500"
:min-height="300"
:max-height="500"
:x="$store.getters.getToolbarState.x"
:y="$store.getters.getToolbarState.y"
:min-width="8 * 15"
:max-width="8 * 25"
:max-height="13 * 26"
:min-height="13 * 25"
:w="toolbarState.w"
:h="toolbarState.h"
:x="toolbarState.x"
:y="toolbarState.y"
>
<t-card style="height: 100%">
<label class="flex ml-1">
<t-checkbox
name="targetingFg"
v-model="$store.getters.getToolbarState.targetingFg"
v-model="toolbarState.targetingFg"
:disabled="
!$store.getters.getTargetingBg && !$store.getters.getTargetingChar
"
@ -28,7 +27,7 @@
<label class="flex ml-1">
<t-checkbox
name="targetingBg"
v-model="$store.getters.getToolbarState.targetingBg"
v-model="toolbarState.targetingBg"
:disabled="
!$store.getters.getTargetingFg && !$store.getters.getTargetingChar
"
@ -39,7 +38,7 @@
<label class="flex ml-1">
<t-checkbox
name="targetingChar"
v-model="$store.getters.getToolbarState.targetingChar"
v-model="toolbarState.targetingChar"
:disabled="
!$store.getters.getTargetingFg && !$store.getters.getTargetingBg
"
@ -61,14 +60,10 @@
<font-awesome-icon :icon="[value.fa, value.icon]" />
</t-button>
<hr />
<BrushPreview />
</t-card>
</vue-draggable-resizable>
</div>
@ -79,32 +74,46 @@ import Colours from "./Colours.vue";
import BrushPreview from "./parts/BrushPreview.vue";
export default {
created() {},
created() {
this.toolbar.x = this.toolbarState.x
this.toolbar.y = this.toolbarState.y
this.toolbar.w = this.toolbarState.w
this.toolbar.h = this.toolbarState.h
},
name: "Toolbar",
components: { Colours, BrushPreview },
data: () => ({
floating: {
width: 0,
height: 0,
toolbar: {
w: 0,
h: 0,
x: 100,
y: 100,
},
}),
computed: {},
computed: {
toolbarState() {
return this.$store.getters.getToolbarState
},
currentAscii() {
return this.$store.getters.currentAscii;
},
},
watch: {},
methods: {
onResize(x, y, width, height) {
this.floating.x = x;
this.floating.y = y;
this.floating.width = width;
this.floating.height = height;
onResize(x, y, w, h) {
this.toolbar.x = x;
this.toolbar.y = y;
this.toolbar.w = w;
this.toolbar.h = h;
this.$store.commit("changeToolBarState", {x: x, y: y, w: this.toolbar.w, h: this.toolbar.h})
},
onDragStop(x, y) {
this.floating.x = x;
this.floating.y = y;
this.toolbar.x = x;
this.toolbar.y = y;
this.$store.commit("changeToolBarState", {x: x, y: y})
this.$store.commit("changeToolBarState", {x: x, y: y, w: this.toolbar.w, h: this.toolbar.h})
},
},
};

View File

@ -0,0 +1,116 @@
<template>
<t-modal
name="create-ascii-modal"
header="Create new ASCII"
:clickToClose="false"
:escToClose="true"
@before-closed="closeNewASCII"
>
Width
<t-input
type="number"
name="width"
v-model="forms.createAscii.width"
min="1"
/>
Height
<t-input
type="number"
name="height"
v-model="forms.createAscii.height"
min="1"
/>
Title
<t-input
type="text"
name="title"
v-model="forms.createAscii.title"
max="128"
/>
<template v-slot:footer>
<div
class="flex justify-between"
@click="$modal.hide('create-ascii-modal')"
>
<t-button type="button"> Cancel </t-button>
<t-button type="button" @click="createNewASCII()"> Ok </t-button>
</div>
</template>
</t-modal>
</template>
<script>
export default {
name: "NewAsciiModal",
created() {},
prop: ['showNewAsciiModal'],
data: () => ({
forms: {
createAscii: {
width: 5,
height: 5,
title: "ascii",
},
},
}),
watch: {
showNewAsciiModal(val, old) {
console.log(val, old)
if (val === true) {
this.createClick()
}
}
},
methods: {
createClick() {
this.forms.createAscii.title = `New ASCII ${this.$store.getters.asciibirdMeta.length}`;
this.$modal.show("create-ascii-modal");
},
createNewASCII() {
const payload = {
title: this.forms.createAscii.title,
key: this.$store.getters.asciibirdMeta.length,
width: this.forms.createAscii.width,
height: this.forms.createAscii.height,
blockWidth: 8,
blockHeight: 13,
x: 247, // the dragable ascii canvas x
y: 24, // the dragable ascii canvas y
blocks: this.create2DArray(this.forms.createAscii.height),
};
// Push all the default ASCII blocks
for (let x = 0; x < payload.width; x++) {
for (let y = 0; y < payload.height; y++) {
payload.blocks[y].push({
bg: null,
fg: null,
char: null,
});
}
}
this.$store.commit("newAsciibirdMeta", payload);
this.$modal.hide("create-ascii-modal");
this.show = false
},
closeNewASCII({ params, cancel }) {
this.forms.createAscii.width = 5;
this.forms.createAscii.height = 5;
this.forms.createAscii.title = "New ASCII";
},
create2DArray(rows) {
const arr = [];
for (let i = 0; i < rows; i++) {
arr[i] = [];
}
return arr;
},
},
};
</script>

File diff suppressed because it is too large Load Diff

View File

@ -119,12 +119,16 @@ export default new Vuex.Store({
targetingFg: true,
targetingBg: true,
targetingChar: true,
x: 24,
y: 28,
x: 8 * 2,
y: 13 * 2,
h: 13 * 25,
w: 8 * 15,
},
debugPanelState: {
x: 26,
y: 344,
x: 8 * 2,
y: 13 * 60,
h: 13 * 3,
w: 8 * 150,
},
blockSizeMultiplier: 1,
},
@ -141,6 +145,8 @@ export default new Vuex.Store({
changeToolBarState(state, payload) {
state.toolbarState.x = payload.x;
state.toolbarState.y = payload.y;
state.toolbarState.w = payload.w;
state.toolbarState.h = payload.h;
},
changeAsciiWidthHeight(state, payload) {
state.asciibirdMeta[state.tab].width = payload.width;

View File

@ -2,10 +2,10 @@
<div>
<div id="canvas-area">
<vue-draggable-resizable
style="z-index: 5"
:grid="[currentAscii.blockHeight, currentAscii.blockWidth]"
:w="canvas.width + currentAscii.blockWidth"
:h="canvas.height + currentAscii.blockHeight"
style="z-index:5;"
:grid="[currentAscii.blockWidth, currentAscii.blockHeight]"
:w="canvas.width"
:h="canvas.height"
:draggable="$store.getters.getCurrentTool === 0"
@resizestop="onCanvasResize"
@dragstop="onCavasDragStop"
@ -141,6 +141,9 @@ export default {
.name === "select"
);
},
dragboxStyle() {
return `z-index: 5;width:${this.canvas.width+4};height:${this.canvas.height+4};`
}
},
watch: {
currentAscii(val, old) {

View File

@ -2567,6 +2567,15 @@ cli-width@^3.0.0:
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
clipboard@^2.0.0:
version "2.0.8"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.8.tgz#ffc6c103dd2967a83005f3f61976aa4655a4cdba"
integrity sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==
dependencies:
good-listener "^1.2.2"
select "^1.1.2"
tiny-emitter "^2.0.0"
clipboardy@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290"
@ -3289,6 +3298,11 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
delegate@^3.1.2:
version "3.2.0"
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
depd@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
@ -4537,6 +4551,13 @@ globby@^9.2.0:
pify "^4.0.1"
slash "^2.0.0"
good-listener@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=
dependencies:
delegate "^3.1.2"
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2:
version "4.2.4"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
@ -7893,6 +7914,11 @@ select-hose@^2.0.0:
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
select@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
selfsigned@^1.10.7:
version "1.10.8"
resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30"
@ -8678,6 +8704,11 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tiny-emitter@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@ -9061,6 +9092,13 @@ vm-browserify@^1.0.1:
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
vue-clipboard2@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/vue-clipboard2/-/vue-clipboard2-0.3.1.tgz#6e551fb7bd384889b28b0da3b12289ed6bca4894"
integrity sha512-H5S/agEDj0kXjUb5GP2c0hCzIXWRBygaWLN3NEFsaI9I3uWin778SFEMt8QRXiPG+7anyjqWiw2lqcxWUSfkYg==
dependencies:
clipboard "^2.0.0"
vue-draggable-resizable@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/vue-draggable-resizable/-/vue-draggable-resizable-2.3.0.tgz#94c433ca748bc1a4d0959ba1c5c0e1c3536cee5b"