| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- <template>
- <ion-modal
- class="invite-modal"
- :isOpen="showInviteModal"
- @didDismiss="showInviteModal = false"
- >
- <div class="content-wrapper">
- <div class="code-wrapper flex flex-col items-center justify-center">
- <div class="">INVITE 3 FRIENDS</div>
- <div class="font-bold">GET 7 DAYS FREE WATCHING</div>
- <img class="mt-2" :src="qrcode" alt="QR Code" />
- <div class="mt-2">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>
|