|
|
@@ -0,0 +1,159 @@
|
|
|
+<template>
|
|
|
+ <ion-modal
|
|
|
+ class="invite-modal"
|
|
|
+ :isOpen="showInviteModal"
|
|
|
+ @didDismiss="showInviteModal = false"
|
|
|
+ >
|
|
|
+ <div class="content-wrapper text-base font-bold">
|
|
|
+ <div class="code-wrapper flex flex-col items-center justify-center">
|
|
|
+ <div class="font-bold">INVITE 3 FRIENDS</div>
|
|
|
+ <div class="">GET 7 DAYS FREE WATCHING</div>
|
|
|
+ <img class="mt-2" :src="qrcode" alt="QR Code" />
|
|
|
+ <div class="mt-2 font-bold">INVITED: 0</div>
|
|
|
+ </div>
|
|
|
+ <div class="flex mt-4 text-center text-sm">
|
|
|
+ <div
|
|
|
+ class="flex-grow border-2 border-white rounded-full box-border h-10 flex items-center justify-center"
|
|
|
+ @click="save"
|
|
|
+ >
|
|
|
+ Save QR Code
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="ml-6 flex-grow bg-prim rounded-full h-10 flex items-center justify-center"
|
|
|
+ @click="share"
|
|
|
+ >
|
|
|
+ Share
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </ion-modal>
|
|
|
+</template>
|
|
|
+<script setup lang="ts">
|
|
|
+import { computed, ref, watch } from "vue";
|
|
|
+import { IonModal } from "@ionic/vue";
|
|
|
+import { useUserStore } from "@/store/user";
|
|
|
+import { storeToRefs } from "pinia";
|
|
|
+import { useQRCode } from "@vueuse/integrations/useQRCode";
|
|
|
+import { Capacitor } from "@capacitor/core";
|
|
|
+import { Filesystem, Directory, Encoding } from "@capacitor/filesystem";
|
|
|
+import { Media } from "@capacitor-community/media";
|
|
|
+import { Share } from "@capacitor/share";
|
|
|
+import toast from "@/plugins/toast";
|
|
|
+import { saveAs } from "file-saver";
|
|
|
+import { useClipboard } from "@vueuse/core";
|
|
|
+import http from "@/plugins/http";
|
|
|
+
|
|
|
+const userStore = useUserStore();
|
|
|
+const { user } = storeToRefs(userStore);
|
|
|
+
|
|
|
+const showInviteModal = ref(false);
|
|
|
+
|
|
|
+const shareUrl = computed(() => {
|
|
|
+ return http.resolve("/static/share2.html?referrer=" + user.value?.id);
|
|
|
+});
|
|
|
+
|
|
|
+const qrcode = useQRCode(shareUrl, { margin: 2, width: 512 });
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ modelValue: Boolean,
|
|
|
+});
|
|
|
+const emit = defineEmits(["update:modelValue"]);
|
|
|
+showInviteModal.value = props.modelValue || false;
|
|
|
+watch(showInviteModal, (val) => {
|
|
|
+ emit("update:modelValue", val);
|
|
|
+});
|
|
|
+watch(
|
|
|
+ () => props.modelValue,
|
|
|
+ (val) => {
|
|
|
+ showInviteModal.value = val;
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+const b64toBlob = (b64Data: string, contentType = "", sliceSize = 512) => {
|
|
|
+ b64Data = b64Data.replace(/data:.+base64,/, "");
|
|
|
+ console.log(b64Data);
|
|
|
+ const byteCharacters = atob(b64Data);
|
|
|
+ const byteArrays = [];
|
|
|
+
|
|
|
+ for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
|
|
|
+ const slice = byteCharacters.slice(offset, offset + sliceSize);
|
|
|
+
|
|
|
+ const byteNumbers = new Array(slice.length);
|
|
|
+ for (let i = 0; i < slice.length; i++) {
|
|
|
+ byteNumbers[i] = slice.charCodeAt(i);
|
|
|
+ }
|
|
|
+
|
|
|
+ const byteArray = new Uint8Array(byteNumbers);
|
|
|
+ byteArrays.push(byteArray);
|
|
|
+ }
|
|
|
+
|
|
|
+ const blob = new Blob(byteArrays, { type: contentType });
|
|
|
+ return blob;
|
|
|
+};
|
|
|
+
|
|
|
+async function save() {
|
|
|
+ if (Capacitor.isNativePlatform()) {
|
|
|
+ //
|
|
|
+ try {
|
|
|
+ const savedFile = await Filesystem.writeFile({
|
|
|
+ path: "share.png",
|
|
|
+ data: qrcode.value,
|
|
|
+ directory: Directory.Cache,
|
|
|
+ });
|
|
|
+ const albums = (await Media.getAlbums()).albums;
|
|
|
+ console.log(albums);
|
|
|
+ const album = albums?.length
|
|
|
+ ? albums.find((a) => a.name === "Camera") || albums[0]
|
|
|
+ : null;
|
|
|
+ await Media.savePhoto({
|
|
|
+ path: savedFile.uri,
|
|
|
+ albumIdentifier: album?.identifier,
|
|
|
+ fileName: "share",
|
|
|
+ });
|
|
|
+ toast("Saved", { type: "success" });
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ saveAs(b64toBlob(qrcode.value), "share.png");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function share() {
|
|
|
+ //
|
|
|
+ if (Capacitor.isNativePlatform()) {
|
|
|
+ await Share.share({
|
|
|
+ title: "Invite Friends",
|
|
|
+ url: shareUrl.value,
|
|
|
+ dialogTitle: "Invite Friends",
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ const clipboard = useClipboard();
|
|
|
+ clipboard.copy(shareUrl.value);
|
|
|
+ toast("Share Link Copied", { type: "success" });
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style lang="less" scoped>
|
|
|
+.invite-modal {
|
|
|
+ --width: fit-content;
|
|
|
+ --min-width: 290px;
|
|
|
+ --height: fit-content;
|
|
|
+ --border-radius: 0;
|
|
|
+ --background: transparent;
|
|
|
+ .content-wrapper {
|
|
|
+ .code-wrapper {
|
|
|
+ width: 290px;
|
|
|
+ height: 350px;
|
|
|
+ background-image: url(@/assets/bg_invite_modal.png);
|
|
|
+ background-size: cover;
|
|
|
+ background-position: center;
|
|
|
+ img {
|
|
|
+ width: 215px;
|
|
|
+ height: 215px;
|
|
|
+ border-radius: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|