Skip to content

Commit 7414b63

Browse files
committed
feat: add shared project configuration
1 parent e5d7485 commit 7414b63

File tree

13 files changed

+388
-34
lines changed

13 files changed

+388
-34
lines changed

.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
VITE_BASE_URL="http://localhost:5173/"

.env.production

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
VITE_BASE_URL="https://nativescript-initializr.jmarvall.com/"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ npm run dev
1111
```
1212

1313
## Roadmap
14-
- Share configuration.
14+
- Share project configuration.
1515
- Allow changing npm version in plugins.
1616
- ✅ Add react plugins for OpenNative.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"dependencies": {
1212
"@octokit/core": "^4.1.0",
1313
"@vueuse/core": "^9.5.0",
14+
"floating-vue": "^2.0.0-beta.20",
1415
"isomorphic-fetch": "^3.0.0",
1516
"jszip": "^3.10.1",
1617
"pinia": "^2.0.24",

src/components/Body.vue

Lines changed: 110 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,57 @@
11
<script setup lang="ts">
2-
import { computed, PropType, reactive, ref } from "vue";
3-
import { Plugin, ProjectMetadata, Flavor } from "@/types/app.types";
2+
import { computed, reactive, ref, defineAsyncComponent } from "vue";
3+
import { Flavor, Plugin, ProjectMetadata } from "@/types/app.types";
44
import RadioGroup from "@/components/RadioGroup.vue";
55
import { FLAVORS, PROJECT_DEFINITION } from "@/constant/constant";
66
import { pluginService } from "@/services/PluginService";
7-
import ItemPlugin from "@/components/ItemPlugin.vue";
8-
import Modal from "@/components/Modal.vue";
9-
import { useWindowSize } from "@vueuse/core";
7+
import { useClipboard, useWindowSize } from "@vueuse/core";
108
import { DownloadProjectService } from "@/services/DownloadProjectService";
11-
import Loading from "@/components/Loading.vue";
12-
import SearchPlugins from "@/components/SearchPlugins.vue";
9+
import { shared } from "@/utils/Shared";
10+
import { SharedProject } from "@/types/share.types";
11+
import { useRoute } from "vue-router";
12+
import { useCommonStore } from "@/plugins/stores/Common.store";
13+
const ItemPlugin = defineAsyncComponent(
14+
() => import("@/components/ItemPlugin.vue")
15+
);
16+
const SearchPlugins = defineAsyncComponent(
17+
() => import("@/components/SearchPlugins.vue")
18+
);
19+
const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
20+
const LoadingDownload = defineAsyncComponent(
21+
() => import("@/components/LoadingDownload.vue")
22+
);
23+
const Loading = defineAsyncComponent(() => import("@/components/Loading.vue"));
1324
1425
const downloadProjectService: DownloadProjectService =
1526
new DownloadProjectService();
1627
const { width } = useWindowSize();
28+
const route = useRoute();
29+
const commonStore = useCommonStore();
1730
const loading = ref(false);
31+
const loadingPlugins = ref(false);
1832
const refDownload = ref<HTMLAnchorElement>();
1933
const formFlavor = ref<Flavor[]>(FLAVORS);
2034
const projectMetadata = reactive<ProjectMetadata>(PROJECT_DEFINITION);
2135
const pluginsStore = ref<Plugin[]>([]);
2236
const addPlugins = ref<Plugin[]>([]);
2337
const openModalAddPlugin = ref(false);
24-
const reactNativePlugins = ref(false);
38+
39+
const flavorSelected = computed<Flavor | undefined>(() =>
40+
formFlavor.value.find((flavor) => flavor.selected)
41+
);
42+
const sharedProjectData = reactive<
43+
SharedProject & { openModal: boolean; dataString: string }
44+
>({
45+
flavor: "",
46+
name: "",
47+
plugins: [],
48+
openModal: false,
49+
rnPlugins: false,
50+
dataString: "",
51+
});
52+
const { copy: copyClipboard } = useClipboard();
2553
2654
const onSelectedFlavor = (index: number) => {
27-
console.log(index);
2855
formFlavor.value.forEach((flavor) => (flavor.selected = false));
2956
formFlavor.value[index].selected = true;
3057
};
@@ -48,15 +75,40 @@ const removePlugin = (plugin: Plugin) => {
4875
4976
const download = async () => {
5077
loading.value = true;
51-
const flavor = formFlavor.value.find((flavor) => flavor.selected);
52-
if (flavor) {
78+
if (flavorSelected.value) {
5379
await downloadProjectService.download(
5480
refDownload.value!,
55-
flavor,
81+
flavorSelected.value,
5682
projectMetadata,
5783
addPlugins.value
5884
);
59-
loading.value = false;
85+
}
86+
loading.value = false;
87+
};
88+
89+
if (shared.isSharedProject(route)) {
90+
loadingPlugins.value = true;
91+
const shareData = shared.retrieveSharedProject(route);
92+
const indexFlavor = FLAVORS.findIndex(
93+
(flavor: Flavor) => flavor.text === shareData.flavor
94+
);
95+
onSelectedFlavor(indexFlavor);
96+
projectMetadata.name = shareData.name;
97+
projectMetadata.description = shareData.description;
98+
projectMetadata.package = shareData.package;
99+
commonStore.enableReactNativePlugins = shareData.rnPlugins;
100+
}
101+
102+
const sharedProject = () => {
103+
if (flavorSelected.value) {
104+
const sharedData = shared.buildURL(
105+
flavorSelected.value,
106+
projectMetadata,
107+
addPlugins.value,
108+
commonStore.enableReactNativePlugins
109+
);
110+
sharedProjectData.openModal = true;
111+
sharedProjectData.dataString = sharedData;
60112
}
61113
};
62114
@@ -67,16 +119,23 @@ pluginService.findAll().then((plugins) => {
67119
return new Date(b.date) - new Date(a.date);
68120
})
69121
);
122+
if (shared.isSharedProject(route)) {
123+
loadingPlugins.value = true;
124+
shared.resolvePlugins(route, pluginsStore.value).then((plugins) => {
125+
addPlugins.value.push(...plugins);
126+
loadingPlugins.value = false;
127+
});
128+
}
70129
});
71130
</script>
72131

73132
<template>
74-
<Loading
133+
<LoadingDownload
75134
:full="true"
76135
message="Generating project"
77136
:show="loading"
78137
position="fixed"
79-
></Loading>
138+
></LoadingDownload>
80139
<div class="px-3 my-8 mb-16">
81140
<a ref="refDownload"></a>
82141
<div class="width-content grid lg:grid-cols-2 grid-cols-1">
@@ -100,7 +159,7 @@ pluginService.findAll().then((plugins) => {
100159
</div>
101160
</div>
102161
</div>
103-
<div class="lg:p-4 p-0 mt-9 lg:border-left">
162+
<div class="lg:p-4 p-0 mt-9 lg:border-left relative">
104163
<div class="flex justify-between items-center border-b pb-4">
105164
<h3 class="text-2xl">Plugins</h3>
106165
<div
@@ -110,7 +169,9 @@ pluginService.findAll().then((plugins) => {
110169
Add plugins
111170
</div>
112171
</div>
113-
<div class="mt-2 added-plugin">
172+
<div class="mt-2 added-plugin relative" style="min-height: 200px">
173+
<Loading :show="loadingPlugins" position="absolute"></Loading>
174+
114175
<div
115176
v-for="(pluginAdded, i) in addPlugins"
116177
:key="i"
@@ -148,6 +209,12 @@ pluginService.findAll().then((plugins) => {
148209
<span class="mdi mdi-github ml-2"></span>
149210
</a>
150211
</div>
212+
<button
213+
class="px-3 md:px-5 py-2 text-white bg font-bold mr-4 rounded-full"
214+
@click="sharedProject"
215+
>
216+
Shared
217+
</button>
151218
<button
152219
class="px-5 py-2 color-bg font-bold mr-4 md:mr-0 rounded-full"
153220
style="background: var(--color-ns-cyan)"
@@ -171,6 +238,32 @@ pluginService.findAll().then((plugins) => {
171238
>
172239
</SearchPlugins>
173240
</Modal>
241+
<Modal
242+
:open="sharedProjectData.openModal"
243+
@close="sharedProjectData.openModal = false"
244+
>
245+
<div
246+
class="p-6 flex flex-col items-center relative"
247+
:style="{ minWidth: width < 900 ? '85vw' : '35vw' }"
248+
>
249+
<h3 class="text-2xl text-left w-full">Copy and share project</h3>
250+
<input
251+
class="mt-8 w-full"
252+
type="text"
253+
v-model="sharedProjectData.dataString"
254+
disabled
255+
/>
256+
<VDropdown :distance="6">
257+
<button
258+
@click="copyClipboard(sharedProjectData.dataString)"
259+
class="mdi mdi-content-copy cursor-pointer mt-4"
260+
></button>
261+
<template #popper>
262+
<div class="text-white p-3">Copied</div>
263+
</template>
264+
</VDropdown>
265+
</div>
266+
</Modal>
174267
</div>
175268
</template>
176269

src/components/Loading.vue

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,7 @@
88
:style="{ background: background, position: position }"
99
>
1010
<div class="width f-column center-vertical center-full">
11-
<lottie-player
12-
src="/loading.json"
13-
background="transparent"
14-
speed="1"
15-
style="width: 300px; height: 300px"
16-
loop
17-
autoplay
18-
></lottie-player>
19-
11+
<div class="loader"></div>
2012
<p class="mt-4 text-center" v-if="message">
2113
{{ message }}
2214
</p>
@@ -55,22 +47,21 @@ const state = reactive({ count: 0 });
5547

5648
<style scoped>
5749
.content-loading {
58-
position: fixed;
5950
left: 0;
6051
top: 0;
61-
width: 100vw;
62-
height: 100vh;
52+
width: 100%;
53+
height: 100%;
6354
display: flex;
6455
justify-content: center;
6556
align-items: center;
6657
min-width: 32px;
6758
min-height: 32px;
68-
z-index: 5;
59+
z-index: 1;
6960
}
7061
.loader {
71-
border: 4px solid var(--c-primary);
62+
border: 4px solid var(--color-ns-cyan);
7263
border-radius: 50%;
73-
border-top: 4px solid var(--c-secondary);
64+
border-top: 4px solid var(--color-ns-cyan);
7465
width: 35px;
7566
height: 35px;
7667
-webkit-animation: spin 2s linear infinite; /* Safari */

src/components/LoadingDownload.vue

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<template>
2+
<div :class="{ full: full }"></div>
3+
4+
<transition name="fade">
5+
<div
6+
class="content-loading width"
7+
v-if="show"
8+
:style="{ background: background, position: position }"
9+
>
10+
<div class="width f-column center-vertical center-full">
11+
<lottie-player
12+
src="/loading.json"
13+
background="transparent"
14+
speed="1"
15+
style="width: 300px; height: 300px"
16+
loop
17+
autoplay
18+
></lottie-player>
19+
20+
<p class="mt-4 text-center" v-if="message">
21+
{{ message }}
22+
</p>
23+
</div>
24+
</div>
25+
</transition>
26+
</template>
27+
28+
<script setup>
29+
import { reactive } from "vue";
30+
defineProps({
31+
text: String,
32+
message: {
33+
type: String,
34+
default: null,
35+
},
36+
show: {
37+
type: Boolean,
38+
default: true,
39+
},
40+
background: {
41+
type: String,
42+
default: "var(--bg)",
43+
},
44+
full: {
45+
type: Boolean,
46+
default: false,
47+
},
48+
position: {
49+
type: String,
50+
default: "absolute",
51+
},
52+
});
53+
const state = reactive({ count: 0 });
54+
</script>
55+
56+
<style scoped>
57+
.content-loading {
58+
position: fixed;
59+
left: 0;
60+
top: 0;
61+
width: 100vw;
62+
height: 100vh;
63+
display: flex;
64+
justify-content: center;
65+
align-items: center;
66+
min-width: 32px;
67+
min-height: 32px;
68+
z-index: 5;
69+
}
70+
.loader {
71+
border: 4px solid var(--c-primary);
72+
border-radius: 50%;
73+
border-top: 4px solid var(--c-secondary);
74+
width: 35px;
75+
height: 35px;
76+
-webkit-animation: spin 2s linear infinite; /* Safari */
77+
animation: spin 2s linear infinite;
78+
}
79+
/* Safari */
80+
@-webkit-keyframes spin {
81+
0% {
82+
-webkit-transform: rotate(0deg);
83+
}
84+
100% {
85+
-webkit-transform: rotate(360deg);
86+
}
87+
}
88+
@keyframes spin {
89+
0% {
90+
transform: rotate(0deg);
91+
}
92+
100% {
93+
transform: rotate(360deg);
94+
}
95+
}
96+
.fade-enter-active,
97+
.fade-leave-active {
98+
transition: opacity 0.25s;
99+
}
100+
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
101+
opacity: 0;
102+
}
103+
.message {
104+
min-width: 80%;
105+
max-width: 80%;
106+
}
107+
</style>

src/components/Modal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export default defineComponent({
4747
},
4848
maxHeight: {
4949
type: String,
50-
default: "100%",
50+
default: "auto",
5151
},
5252
},
5353
emits: ["close"],

src/constant/constant.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,5 @@ export const PROJECT_DEFINITION: ProjectMetadata = {
5252
description: "Description",
5353
package: "com.nativescript.demo",
5454
};
55+
56+
export const BASE_URL = import.meta.env.VITE_BASE_URL;

0 commit comments

Comments
 (0)