mirror of
https://github.com/thelounge/thelounge.git
synced 2024-06-09 01:02:18 +02:00
progress before vue 3
This commit is contained in:
parent
4c98b81e35
commit
aace97056b
|
@ -84,6 +84,8 @@ const vueRules = defineConfig({
|
||||||
"vue/no-v-html": "off",
|
"vue/no-v-html": "off",
|
||||||
"vue/require-default-prop": "off",
|
"vue/require-default-prop": "off",
|
||||||
"vue/v-slot-style": ["error", "longform"],
|
"vue/v-slot-style": ["error", "longform"],
|
||||||
|
// Should be fixable in Vue 3 / when components use Vue.extend()
|
||||||
|
"@typescript-eslint/unbound-method": "off",
|
||||||
},
|
},
|
||||||
}).rules;
|
}).rules;
|
||||||
|
|
||||||
|
@ -113,6 +115,9 @@ const tsRulesTemp = defineConfig({
|
||||||
|
|
||||||
module.exports = defineConfig({
|
module.exports = defineConfig({
|
||||||
root: true,
|
root: true,
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2022,
|
||||||
|
},
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
|
@ -132,7 +137,11 @@ module.exports = defineConfig({
|
||||||
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||||
"prettier",
|
"prettier",
|
||||||
],
|
],
|
||||||
rules: {...baseRules, ...tsRules, ...tsRulesTemp},
|
rules: {
|
||||||
|
...baseRules,
|
||||||
|
...tsRules,
|
||||||
|
...tsRulesTemp,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// TODO: verify
|
// TODO: verify
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,15 +31,6 @@ import ConfirmDialog from "./ConfirmDialog.vue";
|
||||||
import Mentions from "./Mentions.vue";
|
import Mentions from "./Mentions.vue";
|
||||||
import VueApp from "vue";
|
import VueApp from "vue";
|
||||||
|
|
||||||
// This stops Vue from complaining about adding objects to the component context
|
|
||||||
declare module "vue/types/vue" {
|
|
||||||
interface Vue {
|
|
||||||
debouncedResize: () => void;
|
|
||||||
// TODO; type as Timeout
|
|
||||||
dayChangeTimeout: any;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default VueApp.extend({
|
export default VueApp.extend({
|
||||||
name: "App",
|
name: "App",
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -27,30 +27,32 @@
|
||||||
</ChannelWrapper>
|
</ChannelWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
|
import Vue, {PropType} from "vue";
|
||||||
import roundBadgeNumber from "../js/helpers/roundBadgeNumber";
|
import roundBadgeNumber from "../js/helpers/roundBadgeNumber";
|
||||||
|
import {ClientChan, ClientNetwork} from "../js/types";
|
||||||
import ChannelWrapper from "./ChannelWrapper.vue";
|
import ChannelWrapper from "./ChannelWrapper.vue";
|
||||||
|
|
||||||
export default {
|
export default Vue.extend({
|
||||||
name: "Channel",
|
name: "Channel",
|
||||||
components: {
|
components: {
|
||||||
ChannelWrapper,
|
ChannelWrapper,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
isFiltering: Boolean,
|
isFiltering: Boolean,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
unreadCount() {
|
unreadCount(): string {
|
||||||
return roundBadgeNumber(this.channel.unread);
|
return roundBadgeNumber(this.channel.unread);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
close() {
|
close(): void {
|
||||||
this.$root.closeChannel(this.channel);
|
this.$root.closeChannel(this.channel);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -32,15 +32,17 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
|
import Vue, {PropType} from "vue";
|
||||||
import eventbus from "../js/eventbus";
|
import eventbus from "../js/eventbus";
|
||||||
import isChannelCollapsed from "../js/helpers/isChannelCollapsed";
|
import isChannelCollapsed from "../js/helpers/isChannelCollapsed";
|
||||||
|
import {ClientNetwork, ClientChan} from "../js/types";
|
||||||
|
|
||||||
export default {
|
export default Vue.extend({
|
||||||
name: "ChannelWrapper",
|
name: "ChannelWrapper",
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
isFiltering: Boolean,
|
isFiltering: Boolean,
|
||||||
},
|
},
|
||||||
|
@ -53,7 +55,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getAriaLabel() {
|
getAriaLabel(): string {
|
||||||
const extra = [];
|
const extra = [];
|
||||||
const type = this.channel.type;
|
const type = this.channel.type;
|
||||||
|
|
||||||
|
@ -75,14 +77,14 @@ export default {
|
||||||
|
|
||||||
return `${type}: ${this.channel.name} ${extra.length ? `(${extra.join(", ")})` : ""}`;
|
return `${type}: ${this.channel.name} ${extra.length ? `(${extra.join(", ")})` : ""}`;
|
||||||
},
|
},
|
||||||
click() {
|
click(): void {
|
||||||
if (this.isFiltering) {
|
if (this.isFiltering) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$root.switchToChannel(this.channel);
|
this.$root.switchToChannel(this.channel);
|
||||||
},
|
},
|
||||||
openContextMenu(event) {
|
openContextMenu(event): void {
|
||||||
eventbus.emit("contextmenu:channel", {
|
eventbus.emit("contextmenu:channel", {
|
||||||
event: event,
|
event: event,
|
||||||
channel: this.channel,
|
channel: this.channel,
|
||||||
|
@ -90,5 +92,5 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -145,8 +145,8 @@ export default {
|
||||||
MessageSearchForm,
|
MessageSearchForm,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
focused: String,
|
focused: String,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -91,8 +91,8 @@ let autocompletionRef = null;
|
||||||
export default {
|
export default {
|
||||||
name: "ChatInput",
|
name: "ChatInput",
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
"channel.id"() {
|
"channel.id"() {
|
||||||
|
|
|
@ -74,7 +74,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -48,8 +48,8 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -138,7 +138,7 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
link: Object,
|
link: Object,
|
||||||
keepScrollPosition: Function,
|
keepScrollPosition: Function,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -113,8 +113,8 @@ export default {
|
||||||
components: MessageTypes,
|
components: MessageTypes,
|
||||||
props: {
|
props: {
|
||||||
message: Object,
|
message: Object,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
keepScrollPosition: Function,
|
keepScrollPosition: Function,
|
||||||
isPreviousSource: Boolean,
|
isPreviousSource: Boolean,
|
||||||
focused: Boolean,
|
focused: Boolean,
|
||||||
|
|
|
@ -27,7 +27,7 @@ export default {
|
||||||
Message,
|
Message,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
messages: Array,
|
messages: Array,
|
||||||
keepScrollPosition: Function,
|
keepScrollPosition: Function,
|
||||||
focused: Boolean,
|
focused: Boolean,
|
||||||
|
|
|
@ -84,8 +84,8 @@ form.message-search.opened .input-wrapper {
|
||||||
export default {
|
export default {
|
||||||
name: "MessageSearchForm",
|
name: "MessageSearchForm",
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,7 +19,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,7 @@ export default {
|
||||||
ParsedMessage,
|
ParsedMessage,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -19,7 +19,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
export default {
|
export default {
|
||||||
name: "MessageChannelMode",
|
name: "MessageChannelMode",
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
export default {
|
export default {
|
||||||
name: "MessageChannelMode",
|
name: "MessageChannelMode",
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,7 @@ export default {
|
||||||
ParsedMessage,
|
ParsedMessage,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -15,7 +15,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
export default {
|
export default {
|
||||||
name: "MessageTypeRaw",
|
name: "MessageTypeRaw",
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,7 +21,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -123,7 +123,7 @@ export default {
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -209,7 +209,7 @@ import isIgnoredKeybind from "../js/helpers/isIgnoredKeybind";
|
||||||
import distance from "../js/helpers/distance";
|
import distance from "../js/helpers/distance";
|
||||||
import eventbus from "../js/eventbus";
|
import eventbus from "../js/eventbus";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default {
|
||||||
name: "NetworkList",
|
name: "NetworkList",
|
||||||
components: {
|
components: {
|
||||||
JoinChannel,
|
JoinChannel,
|
||||||
|
@ -481,5 +481,5 @@ export default Vue.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -56,7 +56,7 @@ export default {
|
||||||
ChannelWrapper,
|
ChannelWrapper,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
isJoinChannelShown: Boolean,
|
isJoinChannelShown: Boolean,
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
isFiltering: Boolean,
|
isFiltering: Boolean,
|
||||||
|
|
|
@ -7,7 +7,7 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
text: String,
|
text: String,
|
||||||
message: Object,
|
message: Object,
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
},
|
},
|
||||||
render(createElement, context) {
|
render(createElement, context) {
|
||||||
return parse(
|
return parse(
|
||||||
|
|
|
@ -27,8 +27,8 @@ export default {
|
||||||
ParsedMessage,
|
ParsedMessage,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
localetime(date) {
|
localetime(date) {
|
||||||
|
|
|
@ -27,8 +27,8 @@ export default {
|
||||||
ParsedMessage,
|
ParsedMessage,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -25,8 +25,8 @@ export default {
|
||||||
ParsedMessage,
|
ParsedMessage,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
localetime(date) {
|
localetime(date) {
|
||||||
|
|
|
@ -29,8 +29,8 @@ export default {
|
||||||
ParsedMessage,
|
ParsedMessage,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
localetime(date) {
|
localetime(date) {
|
||||||
|
|
|
@ -20,8 +20,8 @@ export default {
|
||||||
user: Object,
|
user: Object,
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
onHover: Function,
|
onHover: Function,
|
||||||
channel: Object,
|
channel: Object as PropType<ClientChan>,
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
mode() {
|
mode() {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import storage from "../localStorage";
|
||||||
import {router, switchToChannel, navigate} from "../router";
|
import {router, switchToChannel, navigate} from "../router";
|
||||||
import store from "../store";
|
import store from "../store";
|
||||||
import parseIrcUri from "../helpers/parseIrcUri";
|
import parseIrcUri from "../helpers/parseIrcUri";
|
||||||
|
import {ClientChan, ClientNetwork, InitClientChan} from "../types";
|
||||||
|
|
||||||
socket.on("init", function (data) {
|
socket.on("init", function (data) {
|
||||||
store.commit("networks", mergeNetworkData(data.networks));
|
store.commit("networks", mergeNetworkData(data.networks));
|
||||||
|
@ -47,8 +48,9 @@ socket.on("init", function (data) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function mergeNetworkData(newNetworks) {
|
function mergeNetworkData(newNetworks: ClientNetwork[]) {
|
||||||
const collapsedNetworks = new Set(JSON.parse(storage.get("thelounge.networks.collapsed")));
|
const stored = storage.get("thelounge.networks.collapsed");
|
||||||
|
const collapsedNetworks = stored ? new Set(JSON.parse(stored)) : new Set();
|
||||||
|
|
||||||
for (let n = 0; n < newNetworks.length; n++) {
|
for (let n = 0; n < newNetworks.length; n++) {
|
||||||
const network = newNetworks[n];
|
const network = newNetworks[n];
|
||||||
|
@ -74,7 +76,7 @@ function mergeNetworkData(newNetworks) {
|
||||||
if (key === "channels") {
|
if (key === "channels") {
|
||||||
currentNetwork.channels = mergeChannelData(
|
currentNetwork.channels = mergeChannelData(
|
||||||
currentNetwork.channels,
|
currentNetwork.channels,
|
||||||
network.channels
|
network.channels as InitClientChan[]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
currentNetwork[key] = network[key];
|
currentNetwork[key] = network[key];
|
||||||
|
@ -87,7 +89,7 @@ function mergeNetworkData(newNetworks) {
|
||||||
return newNetworks;
|
return newNetworks;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeChannelData(oldChannels, newChannels) {
|
function mergeChannelData(oldChannels: InitClientChan[], newChannels: InitClientChan[]) {
|
||||||
for (let c = 0; c < newChannels.length; c++) {
|
for (let c = 0; c < newChannels.length; c++) {
|
||||||
const channel = newChannels[c];
|
const channel = newChannels[c];
|
||||||
const currentChannel = oldChannels.find((chan) => chan.id === channel.id);
|
const currentChannel = oldChannels.find((chan) => chan.id === channel.id);
|
||||||
|
@ -131,7 +133,7 @@ function mergeChannelData(oldChannels, newChannels) {
|
||||||
// on the client, and decide whether theres more messages to load from server
|
// on the client, and decide whether theres more messages to load from server
|
||||||
if (key === "totalMessages") {
|
if (key === "totalMessages") {
|
||||||
currentChannel.moreHistoryAvailable =
|
currentChannel.moreHistoryAvailable =
|
||||||
channel.totalMessages > currentChannel.messages.length;
|
channel.totalMessages! > currentChannel.messages.length;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -167,10 +169,12 @@ function handleQueryParams() {
|
||||||
if (params.has("uri")) {
|
if (params.has("uri")) {
|
||||||
// Set default connection settings from IRC protocol links
|
// Set default connection settings from IRC protocol links
|
||||||
const uri = params.get("uri");
|
const uri = params.get("uri");
|
||||||
const queryParams = parseIrcUri(uri);
|
const queryParams = parseIrcUri(uri as string);
|
||||||
|
|
||||||
cleanParams();
|
cleanParams();
|
||||||
router.push({name: "Connect", query: queryParams});
|
router.push({name: "Connect", query: queryParams}).catch(() => {
|
||||||
|
// Ignore errors
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else if (document.body.classList.contains("public") && document.location.search) {
|
} else if (document.body.classList.contains("public") && document.location.search) {
|
||||||
|
@ -178,7 +182,9 @@ function handleQueryParams() {
|
||||||
const queryParams = Object.fromEntries(params.entries());
|
const queryParams = Object.fromEntries(params.entries());
|
||||||
|
|
||||||
cleanParams();
|
cleanParams();
|
||||||
router.push({name: "Connect", query: queryParams});
|
router.push({name: "Connect", query: queryParams}).catch(() => {
|
||||||
|
// Ignore errors
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import Vuex from "vuex";
|
import Vuex, {GetterTree, Store} from "vuex";
|
||||||
import {createSettingsStore} from "./store-settings";
|
import {createSettingsStore} from "./store-settings";
|
||||||
import storage from "./localStorage";
|
import storage from "./localStorage";
|
||||||
import {ClientChan, ClientNetwork} from "./types";
|
import type {ClientChan, ClientNetwork, InitClientChan} from "./types";
|
||||||
|
|
||||||
const appName = document.title;
|
const appName = document.title;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ function detectDesktopNotificationState() {
|
||||||
return "blocked";
|
return "blocked";
|
||||||
}
|
}
|
||||||
|
|
||||||
export type State = {
|
export interface State {
|
||||||
appLoaded: boolean;
|
appLoaded: boolean;
|
||||||
activeChannel: {
|
activeChannel: {
|
||||||
network: ClientNetwork;
|
network: ClientNetwork;
|
||||||
|
@ -54,13 +54,15 @@ export type State = {
|
||||||
} | null;
|
} | null;
|
||||||
messageSearchInProgress: boolean;
|
messageSearchInProgress: boolean;
|
||||||
searchEnabled: boolean;
|
searchEnabled: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type SettingsState = {};
|
const store = new Store<State>({
|
||||||
const store = new Vuex.Store<Omit<State, "settings">>({
|
|
||||||
state: {
|
state: {
|
||||||
appLoaded: false,
|
appLoaded: false,
|
||||||
activeChannel: null,
|
activeChannel: {
|
||||||
|
network: {} as ClientNetwork,
|
||||||
|
channel: {} as ClientChan,
|
||||||
|
},
|
||||||
currentUserVisibleError: null,
|
currentUserVisibleError: null,
|
||||||
desktopNotificationState: detectDesktopNotificationState(),
|
desktopNotificationState: detectDesktopNotificationState(),
|
||||||
isAutoCompleting: false,
|
isAutoCompleting: false,
|
||||||
|
@ -162,14 +164,16 @@ const store = new Vuex.Store<Omit<State, "settings">>({
|
||||||
state.messageSearchResults = value;
|
state.messageSearchResults = value;
|
||||||
},
|
},
|
||||||
addMessageSearchResults(state, value) {
|
addMessageSearchResults(state, value) {
|
||||||
if (state.messageSearchResults!.results) {
|
// Append the search results and add networks and channels to new messages
|
||||||
// Append the search results and add networks and channels to new messages
|
if (!state.messageSearchResults) {
|
||||||
value.results = [...state.messageSearchResults!.results, ...value.results];
|
state.messageSearchResults = {results: []};
|
||||||
} else {
|
|
||||||
value.results = value.results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.messageSearchResults = value;
|
const results = [...state.messageSearchResults.results, ...value.results];
|
||||||
|
|
||||||
|
state.messageSearchResults = {
|
||||||
|
results,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -179,11 +183,11 @@ const store = new Vuex.Store<Omit<State, "settings">>({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
findChannelOnCurrentNetwork: (state) => (name) => {
|
findChannelOnCurrentNetwork: (state) => (name: string) => {
|
||||||
name = name.toLowerCase();
|
name = name.toLowerCase();
|
||||||
return state.activeChannel?.network.channels.find((c) => c.name.toLowerCase() === name);
|
return state.activeChannel?.network.channels.find((c) => c.name.toLowerCase() === name);
|
||||||
},
|
},
|
||||||
findChannelOnNetwork: (state) => (networkUuid, channelName) => {
|
findChannelOnNetwork: (state) => (networkUuid: string, channelName: string) => {
|
||||||
for (const network of state.networks) {
|
for (const network of state.networks) {
|
||||||
if (network.uuid !== networkUuid) {
|
if (network.uuid !== networkUuid) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -198,7 +202,7 @@ const store = new Vuex.Store<Omit<State, "settings">>({
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
findChannel: (state) => (id) => {
|
findChannel: (state) => (id: number) => {
|
||||||
for (const network of state.networks) {
|
for (const network of state.networks) {
|
||||||
for (const channel of network.channels) {
|
for (const channel of network.channels) {
|
||||||
if (channel.id === id) {
|
if (channel.id === id) {
|
||||||
|
@ -209,7 +213,7 @@ const store = new Vuex.Store<Omit<State, "settings">>({
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
findNetwork: (state) => (uuid) => {
|
findNetwork: (state) => (uuid: string) => {
|
||||||
for (const network of state.networks) {
|
for (const network of state.networks) {
|
||||||
if (network.uuid === uuid) {
|
if (network.uuid === uuid) {
|
||||||
return network;
|
return network;
|
||||||
|
@ -233,14 +237,16 @@ const store = new Vuex.Store<Omit<State, "settings">>({
|
||||||
|
|
||||||
return highlightCount;
|
return highlightCount;
|
||||||
},
|
},
|
||||||
|
// TODO: type
|
||||||
title(state, getters) {
|
title(state, getters) {
|
||||||
const alertEventCount = getters.highlightCount ? `(${getters.highlightCount}) ` : "";
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||||
|
const alertEventCount = getters?.highlightCount ? `(${getters.highlightCount}) ` : "";
|
||||||
|
|
||||||
const channelname = state.activeChannel ? `${state.activeChannel.channel.name} — ` : "";
|
const channelname = state.activeChannel ? `${state.activeChannel.channel.name} — ` : "";
|
||||||
|
|
||||||
return alertEventCount + channelname + appName;
|
return alertEventCount + channelname + appName;
|
||||||
},
|
},
|
||||||
initChannel: () => (channel) => {
|
initChannel: () => (channel: InitClientChan) => {
|
||||||
// TODO: This should be a mutation
|
// TODO: This should be a mutation
|
||||||
channel.pendingMessage = "";
|
channel.pendingMessage = "";
|
||||||
channel.inputHistoryPosition = 0;
|
channel.inputHistoryPosition = 0;
|
||||||
|
@ -250,20 +256,20 @@ const store = new Vuex.Store<Omit<State, "settings">>({
|
||||||
.filter((m) => m.self && m.text && m.type === "message")
|
.filter((m) => m.self && m.text && m.type === "message")
|
||||||
.map((m) => m.text)
|
.map((m) => m.text)
|
||||||
.reverse()
|
.reverse()
|
||||||
.slice(null, 99)
|
.slice(0, 99)
|
||||||
);
|
);
|
||||||
channel.historyLoading = false;
|
channel.historyLoading = false;
|
||||||
channel.scrolledToBottom = true;
|
channel.scrolledToBottom = true;
|
||||||
channel.editTopic = false;
|
channel.editTopic = false;
|
||||||
|
|
||||||
channel.moreHistoryAvailable = channel.totalMessages > channel.messages.length;
|
channel.moreHistoryAvailable = channel.totalMessages! > channel.messages.length;
|
||||||
delete channel.totalMessages;
|
delete channel.totalMessages;
|
||||||
|
|
||||||
if (channel.type === "channel") {
|
if (channel.type === "channel") {
|
||||||
channel.usersOutdated = true;
|
channel.usersOutdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return channel;
|
return channel as ClientChan;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
15
client/js/types.d.ts
vendored
15
client/js/types.d.ts
vendored
|
@ -5,6 +5,7 @@ declare module "*.vue" {
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
export default Vue;
|
export default Vue;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LoungeWindow extends Window {
|
interface LoungeWindow extends Window {
|
||||||
g_TheLoungeRemoveLoading?: () => void;
|
g_TheLoungeRemoveLoading?: () => void;
|
||||||
}
|
}
|
||||||
|
@ -12,8 +13,22 @@ interface LoungeWindow extends Window {
|
||||||
type ClientChan = Chan & {
|
type ClientChan = Chan & {
|
||||||
moreHistoryAvailable: boolean;
|
moreHistoryAvailable: boolean;
|
||||||
editTopic: boolean;
|
editTopic: boolean;
|
||||||
|
|
||||||
|
// these are added in store/initChannel
|
||||||
|
pendingMessage: string;
|
||||||
|
inputHistoryPosition: number;
|
||||||
|
inputHistory: string[];
|
||||||
|
historyLoading: boolean;
|
||||||
|
scrolledToBottom: boolean;
|
||||||
|
usersOutdated: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type InitClientChan = ClientChan & {
|
||||||
|
// total messages is deleted after its use when init event is sent/handled
|
||||||
|
totalMessages?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ClientNetwork = Network & {
|
type ClientNetwork = Network & {
|
||||||
isJoinChannelShown: boolean;
|
isJoinChannelShown: boolean;
|
||||||
|
isCollapsed: boolean;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@ import constants from "./constants";
|
||||||
|
|
||||||
import "../css/style.css";
|
import "../css/style.css";
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import store from "./store";
|
import store, {State} from "./store";
|
||||||
import App from "../components/App.vue";
|
import App from "../components/App.vue";
|
||||||
import storage from "./localStorage";
|
import storage from "./localStorage";
|
||||||
import {router, navigate} from "./router";
|
import {router, navigate} from "./router";
|
||||||
|
@ -13,20 +13,26 @@ import "./socket-events";
|
||||||
import "./webpush";
|
import "./webpush";
|
||||||
import "./keybinds";
|
import "./keybinds";
|
||||||
import {ClientChan} from "./types";
|
import {ClientChan} from "./types";
|
||||||
|
import {Store} from "vuex";
|
||||||
|
|
||||||
const favicon = document.getElementById("favicon");
|
const favicon = document.getElementById("favicon");
|
||||||
const faviconNormal = favicon?.getAttribute("href") || "";
|
const faviconNormal = favicon?.getAttribute("href") || "";
|
||||||
const faviconAlerted = favicon?.dataset.other || "";
|
const faviconAlerted = favicon?.dataset.other || "";
|
||||||
|
|
||||||
type Data = {};
|
declare module "vue/types/vue" {
|
||||||
export type Methods = {
|
interface Vue {
|
||||||
switchToChannel: (channel: ClientChan) => void;
|
debouncedResize: () => void;
|
||||||
closeChannel: (channel: ClientChan) => void;
|
// TODO; type as Timeout
|
||||||
};
|
dayChangeTimeout: any;
|
||||||
type Computed = {};
|
|
||||||
type Props = {};
|
|
||||||
|
|
||||||
new Vue<Data, Methods, Computed, Props>({
|
switchToChannel: (channel: ClientChan) => void;
|
||||||
|
closeChannel: (channel: ClientChan) => void;
|
||||||
|
|
||||||
|
$store: Store<State>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new Vue({
|
||||||
el: "#viewport",
|
el: "#viewport",
|
||||||
router,
|
router,
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
|
@ -111,6 +111,7 @@
|
||||||
"@typescript-eslint/parser": "5.22.0",
|
"@typescript-eslint/parser": "5.22.0",
|
||||||
"@vue/babel-helper-vue-jsx-merge-props": "1.2.1",
|
"@vue/babel-helper-vue-jsx-merge-props": "1.2.1",
|
||||||
"@vue/babel-preset-jsx": "1.2.4",
|
"@vue/babel-preset-jsx": "1.2.4",
|
||||||
|
"@vue/runtime-core": "3.2.35",
|
||||||
"@vue/runtime-dom": "3.2.33",
|
"@vue/runtime-dom": "3.2.33",
|
||||||
"@vue/server-test-utils": "1.3.0",
|
"@vue/server-test-utils": "1.3.0",
|
||||||
"@vue/test-utils": "1.3.0",
|
"@vue/test-utils": "1.3.0",
|
||||||
|
|
|
@ -4,11 +4,22 @@ import express from "express";
|
||||||
|
|
||||||
import log from "../log";
|
import log from "../log";
|
||||||
|
|
||||||
|
import webpack from "webpack";
|
||||||
|
import config from "../../webpack.config";
|
||||||
|
|
||||||
export default (app: express.Application) => {
|
export default (app: express.Application) => {
|
||||||
log.debug("Starting server in development mode");
|
log.debug("Starting server in development mode");
|
||||||
|
|
||||||
const webpack = require("webpack");
|
const webpackConfig = config(undefined, {mode: "production"});
|
||||||
const webpackConfig = require("../../webpack.config.js")(undefined, { mode: "production" });
|
|
||||||
|
if (
|
||||||
|
!webpackConfig ||
|
||||||
|
!webpackConfig.plugins?.length ||
|
||||||
|
!webpackConfig.entry ||
|
||||||
|
!webpackConfig.entry["js/bundle.js"]
|
||||||
|
) {
|
||||||
|
throw new Error("No valid production webpack config found");
|
||||||
|
}
|
||||||
|
|
||||||
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
|
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
|
||||||
webpackConfig.entry["js/bundle.js"].push(
|
webpackConfig.entry["js/bundle.js"].push(
|
||||||
|
|
|
@ -15,7 +15,7 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
text: String,
|
text: String,
|
||||||
message: Object,
|
message: Object,
|
||||||
network: Object,
|
network: Object as PropType<ClientNetwork>,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,189 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const webpack = require("webpack");
|
|
||||||
const path = require("path");
|
|
||||||
const CopyPlugin = require("copy-webpack-plugin");
|
|
||||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|
||||||
const VueLoaderPlugin = require("vue-loader/lib/plugin");
|
|
||||||
const Helper = require("./src/helper.js");
|
|
||||||
const babelConfig = require("./babel.config.cjs");
|
|
||||||
|
|
||||||
const isProduction = process.env.NODE_ENV === "production";
|
|
||||||
const config = {
|
|
||||||
mode: isProduction ? "production" : "development",
|
|
||||||
entry: {
|
|
||||||
"js/bundle.js": [path.resolve(__dirname, "client/js/vue.js")],
|
|
||||||
},
|
|
||||||
devtool: "source-map",
|
|
||||||
output: {
|
|
||||||
clean: true, // Clean the output directory before emit.
|
|
||||||
path: path.resolve(__dirname, "public"),
|
|
||||||
filename: "[name]",
|
|
||||||
publicPath: "/",
|
|
||||||
},
|
|
||||||
performance: {
|
|
||||||
hints: false,
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.vue$/,
|
|
||||||
use: {
|
|
||||||
loader: "vue-loader",
|
|
||||||
options: {
|
|
||||||
compilerOptions: {
|
|
||||||
preserveWhitespace: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: MiniCssExtractPlugin.loader,
|
|
||||||
options: {
|
|
||||||
esModule: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
loader: "css-loader",
|
|
||||||
options: {
|
|
||||||
url: false,
|
|
||||||
importLoaders: 1,
|
|
||||||
sourceMap: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
loader: "postcss-loader",
|
|
||||||
options: {
|
|
||||||
sourceMap: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
include: [path.resolve(__dirname, "client")],
|
|
||||||
use: {
|
|
||||||
loader: "babel-loader",
|
|
||||||
options: babelConfig,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
optimization: {
|
|
||||||
splitChunks: {
|
|
||||||
cacheGroups: {
|
|
||||||
commons: {
|
|
||||||
test: /[\\/]node_modules[\\/]/,
|
|
||||||
name: "js/bundle.vendor.js",
|
|
||||||
chunks: "all",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
externals: {
|
|
||||||
json3: "JSON", // socket.io uses json3.js, but we do not target any browsers that need it
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new VueLoaderPlugin(),
|
|
||||||
new MiniCssExtractPlugin({
|
|
||||||
filename: "css/style.css",
|
|
||||||
}),
|
|
||||||
new CopyPlugin({
|
|
||||||
patterns: [
|
|
||||||
{
|
|
||||||
from: "./node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff*",
|
|
||||||
to: "fonts/[name][ext]",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "./client/js/loading-error-handlers.js",
|
|
||||||
to: "js/[name][ext]",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "./client/*",
|
|
||||||
to: "[name][ext]",
|
|
||||||
globOptions: {
|
|
||||||
ignore: ["**/index.html.tpl", "**/service-worker.js"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "./client/service-worker.js",
|
|
||||||
to: "[name][ext]",
|
|
||||||
transform(content) {
|
|
||||||
return content
|
|
||||||
.toString()
|
|
||||||
.replace(
|
|
||||||
"__HASH__",
|
|
||||||
isProduction ? Helper.getVersionCacheBust() : "dev"
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "./client/audio/*",
|
|
||||||
to: "audio/[name][ext]",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "./client/img/*",
|
|
||||||
to: "img/[name][ext]",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "./client/themes/*",
|
|
||||||
to: "themes/[name][ext]",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
// socket.io uses debug, we don't need it
|
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
|
||||||
/debug/,
|
|
||||||
path.resolve(__dirname, "scripts/noop.js")
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = (env, argv) => {
|
|
||||||
if (argv.mode === "development") {
|
|
||||||
config.target = "node";
|
|
||||||
config.devtool = "eval";
|
|
||||||
config.stats = "errors-only";
|
|
||||||
config.output.path = path.resolve(__dirname, "test/public");
|
|
||||||
config.entry = {
|
|
||||||
"testclient.js": [path.resolve(__dirname, "test/client/index.js")],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add the istanbul plugin to babel-loader options
|
|
||||||
for (const rule of config.module.rules) {
|
|
||||||
if (rule.use.loader === "babel-loader") {
|
|
||||||
rule.use.options.plugins = ["istanbul"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// `optimization.splitChunks` is incompatible with a `target` of `node`. See:
|
|
||||||
// - https://github.com/zinserjan/mocha-webpack/issues/84
|
|
||||||
// - https://github.com/webpack/webpack/issues/6727#issuecomment-372589122
|
|
||||||
config.optimization.splitChunks = false;
|
|
||||||
|
|
||||||
// Disable plugins like copy files, it is not required
|
|
||||||
config.plugins = [
|
|
||||||
new VueLoaderPlugin(),
|
|
||||||
new MiniCssExtractPlugin({
|
|
||||||
filename: "css/style.css",
|
|
||||||
}),
|
|
||||||
// Client tests that require Vue may end up requireing socket.io
|
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
|
||||||
/js(\/|\\)socket\.js/,
|
|
||||||
path.resolve(__dirname, "scripts/noop.js")
|
|
||||||
),
|
|
||||||
|
|
||||||
// "Fixes" Critical dependency: the request of a dependency is an expression
|
|
||||||
new webpack.ContextReplacementPlugin(/vue-server-renderer$/),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argv.mode === "production") {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
};
|
|
20
yarn.lock
20
yarn.lock
|
@ -1874,6 +1874,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/shared" "3.2.33"
|
"@vue/shared" "3.2.33"
|
||||||
|
|
||||||
|
"@vue/reactivity@3.2.35":
|
||||||
|
version "3.2.35"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.35.tgz#c66af289f3beda6aba63c264db9c6acd607d1c73"
|
||||||
|
integrity sha512-6j9N9R1SwHVcJas4YqAzwdRS/cgmj3Z9aUert5Mv1jk5B9H9ivN/zot/fgMUbseWXigkkmX60OsfRbz49o8kCw==
|
||||||
|
dependencies:
|
||||||
|
"@vue/shared" "3.2.35"
|
||||||
|
|
||||||
"@vue/runtime-core@3.2.33":
|
"@vue/runtime-core@3.2.33":
|
||||||
version "3.2.33"
|
version "3.2.33"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.33.tgz#2df8907c85c37c3419fbd1bdf1a2df097fa40df2"
|
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.33.tgz#2df8907c85c37c3419fbd1bdf1a2df097fa40df2"
|
||||||
|
@ -1882,6 +1889,14 @@
|
||||||
"@vue/reactivity" "3.2.33"
|
"@vue/reactivity" "3.2.33"
|
||||||
"@vue/shared" "3.2.33"
|
"@vue/shared" "3.2.33"
|
||||||
|
|
||||||
|
"@vue/runtime-core@3.2.35":
|
||||||
|
version "3.2.35"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.35.tgz#a87bd5214ff31f9dc6542f5c498d4f3543c6ea8f"
|
||||||
|
integrity sha512-P8AeGPRGyIiYdOdvLc/7KR8VSdbUGG8Jxdx6Xlj5okEjyV9IYxeHRIQIoye85K0lZXBH4zuh1syD1mX+oZ0KqQ==
|
||||||
|
dependencies:
|
||||||
|
"@vue/reactivity" "3.2.35"
|
||||||
|
"@vue/shared" "3.2.35"
|
||||||
|
|
||||||
"@vue/runtime-dom@3.2.33":
|
"@vue/runtime-dom@3.2.33":
|
||||||
version "3.2.33"
|
version "3.2.33"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.33.tgz#123b8969247029ea0d9c1983676d4706a962d848"
|
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.33.tgz#123b8969247029ea0d9c1983676d4706a962d848"
|
||||||
|
@ -1904,6 +1919,11 @@
|
||||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.33.tgz#69a8c99ceb37c1b031d5cc4aec2ff1dc77e1161e"
|
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.33.tgz#69a8c99ceb37c1b031d5cc4aec2ff1dc77e1161e"
|
||||||
integrity sha512-UBc1Pg1T3yZ97vsA2ueER0F6GbJebLHYlEi4ou1H5YL4KWvMOOWwpYo9/QpWq93wxKG6Wo13IY74Hcn/f7c7Bg==
|
integrity sha512-UBc1Pg1T3yZ97vsA2ueER0F6GbJebLHYlEi4ou1H5YL4KWvMOOWwpYo9/QpWq93wxKG6Wo13IY74Hcn/f7c7Bg==
|
||||||
|
|
||||||
|
"@vue/shared@3.2.35":
|
||||||
|
version "3.2.35"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.35.tgz#fb60530fa009dc21473386a7639eed833877cb0f"
|
||||||
|
integrity sha512-/sxDqMcy0MsfQ3LQixKYDxIinDYNy1dXTsF2Am0pv0toImWabymFQ8cFmPJnPt+gh5ElKwwn7KzQcDbLHar60A==
|
||||||
|
|
||||||
"@vue/test-utils@1.3.0":
|
"@vue/test-utils@1.3.0":
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.3.0.tgz#d563decdcd9c68a7bca151d4179a2bfd6d5c3e15"
|
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.3.0.tgz#d563decdcd9c68a7bca151d4179a2bfd6d5c3e15"
|
||||||
|
|
Loading…
Reference in a new issue