ShareModal.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <template>
  2. <ion-modal
  3. class="invite-modal"
  4. :isOpen="showInviteModal"
  5. @didDismiss="showInviteModal = false"
  6. >
  7. <div class="content-wrapper">
  8. <div class="code-wrapper flex flex-col items-center justify-center">
  9. <div class="">INVITE 3 FRIENDS</div>
  10. <div class="font-bold">GET 7 DAYS FREE WATCHING</div>
  11. <img class="mt-2" :src="qrcode" alt="QR Code" />
  12. <div class="mt-2">INVITED: 0</div>
  13. </div>
  14. <div class="flex mt-4 text-center text-sm">
  15. <div
  16. class="flex-grow border-2 border-white rounded-full box-border h-10 flex items-center justify-center"
  17. @click="save"
  18. >
  19. Save QR Code
  20. </div>
  21. <div
  22. class="ml-6 flex-grow bg-prim rounded-full h-10 flex items-center justify-center"
  23. @click="share"
  24. >
  25. Share
  26. </div>
  27. </div>
  28. </div>
  29. </ion-modal>
  30. </template>
  31. <script setup lang="ts">
  32. import { computed, ref, watch } from "vue";
  33. import { IonModal } from "@ionic/vue";
  34. import { useUserStore } from "@/store/user";
  35. import { storeToRefs } from "pinia";
  36. import { useQRCode } from "@vueuse/integrations/useQRCode";
  37. import { Capacitor } from "@capacitor/core";
  38. import { Filesystem, Directory, Encoding } from "@capacitor/filesystem";
  39. import { Media } from "@capacitor-community/media";
  40. import { Share } from "@capacitor/share";
  41. import toast from "@/plugins/toast";
  42. import { saveAs } from "file-saver";
  43. import { useClipboard } from "@vueuse/core";
  44. import http from "@/plugins/http";
  45. const userStore = useUserStore();
  46. const { user } = storeToRefs(userStore);
  47. const showInviteModal = ref(false);
  48. const shareUrl = computed(() => {
  49. return http.resolve("/static/share2.html?referrer=" + user.value?.id);
  50. });
  51. const qrcode = useQRCode(shareUrl, { margin: 2, width: 512 });
  52. const props = defineProps({
  53. modelValue: Boolean,
  54. });
  55. const emit = defineEmits(["update:modelValue"]);
  56. showInviteModal.value = props.modelValue || false;
  57. watch(showInviteModal, (val) => {
  58. emit("update:modelValue", val);
  59. });
  60. watch(
  61. () => props.modelValue,
  62. (val) => {
  63. showInviteModal.value = val;
  64. }
  65. );
  66. const b64toBlob = (b64Data: string, contentType = "", sliceSize = 512) => {
  67. b64Data = b64Data.replace(/data:.+base64,/, "");
  68. console.log(b64Data);
  69. const byteCharacters = atob(b64Data);
  70. const byteArrays = [];
  71. for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
  72. const slice = byteCharacters.slice(offset, offset + sliceSize);
  73. const byteNumbers = new Array(slice.length);
  74. for (let i = 0; i < slice.length; i++) {
  75. byteNumbers[i] = slice.charCodeAt(i);
  76. }
  77. const byteArray = new Uint8Array(byteNumbers);
  78. byteArrays.push(byteArray);
  79. }
  80. const blob = new Blob(byteArrays, { type: contentType });
  81. return blob;
  82. };
  83. async function save() {
  84. if (Capacitor.isNativePlatform()) {
  85. //
  86. try {
  87. const savedFile = await Filesystem.writeFile({
  88. path: "share.png",
  89. data: qrcode.value,
  90. directory: Directory.Cache,
  91. });
  92. const albums = (await Media.getAlbums()).albums;
  93. console.log(albums);
  94. const album = albums?.length
  95. ? albums.find((a) => a.name === "Camera") || albums[0]
  96. : null;
  97. await Media.savePhoto({
  98. path: savedFile.uri,
  99. albumIdentifier: album?.identifier,
  100. fileName: "share",
  101. });
  102. toast("Saved", { type: "success" });
  103. } catch (e) {
  104. console.log(e);
  105. }
  106. } else {
  107. saveAs(b64toBlob(qrcode.value), "share.png");
  108. }
  109. }
  110. async function share() {
  111. //
  112. if (Capacitor.isNativePlatform()) {
  113. await Share.share({
  114. title: "Invite Friends",
  115. url: shareUrl.value,
  116. dialogTitle: "Invite Friends",
  117. });
  118. } else {
  119. const clipboard = useClipboard();
  120. clipboard.copy(shareUrl.value);
  121. toast("Share Link Copied", { type: "success" });
  122. }
  123. }
  124. </script>
  125. <style lang="less" scoped>
  126. .invite-modal {
  127. --width: fit-content;
  128. --min-width: 290px;
  129. --height: fit-content;
  130. --border-radius: 0;
  131. --background: transparent;
  132. .content-wrapper {
  133. .code-wrapper {
  134. width: 290px;
  135. height: 350px;
  136. background-image: url(@/assets/bg_invite_modal.png);
  137. background-size: cover;
  138. background-position: center;
  139. img {
  140. width: 215px;
  141. height: 215px;
  142. border-radius: 8px;
  143. }
  144. }
  145. }
  146. }
  147. </style>