Add (nav): share button

This commit is contained in:
2023-11-23 15:03:45 +08:00
parent 8d9fb190ef
commit a8d295dae9
20 changed files with 206 additions and 58 deletions

View File

@@ -30,8 +30,7 @@ public function searchResults(Request $request, $query)
$rss_post_keyword = RssPostKeyword::where('value_lowercased', strtolower($query))->first();
if (!is_null($rss_post_keyword))
{
if (! is_null($rss_post_keyword)) {
$query = $rss_post_keyword->value;
}
@@ -45,14 +44,12 @@ public function searchResults(Request $request, $query)
$top_rss_keywords = HybridTopRssPostKeywords::get(1, 5);
$description = "Stay updated with " . $query;
$description = 'Stay updated with '.$query;
foreach ($top_rss_keywords as $rss_keyword)
{
$description .= ", " . $rss_keyword->value;
foreach ($top_rss_keywords as $rss_keyword) {
$description .= ', '.$rss_keyword->value;
}
$description .= " and 1000+ other news topics with 1-minute news bites with FutureWalker.";
$description .= ' and 1000+ other news topics with 1-minute news bites with FutureWalker.';
SEOTools::metatags();
SEOTools::twitter();
@@ -95,7 +92,7 @@ public function index(Request $request)
]);
$title = '1-minute AI & Tech News Bites: Updated Hourly';
$description = "Stay updated over 1000+ news topics summarised to 1-minute news bites with FutureWalker.";
$description = 'Stay updated over 1000+ news topics summarised to 1-minute news bites with FutureWalker.';
SEOTools::metatags();
SEOTools::twitter();
@@ -143,18 +140,16 @@ public function category(Request $request, $category_slug)
['name' => $category->name, 'url' => null],
]);
$title = 'AI & Tech ' . "$category->name" . ": Updated Hourly" ;
$title = 'AI & Tech '."$category->name".': Updated Hourly';
$top_rss_keywords = HybridTopRssPostKeywords::get(1, 10);
$description = "Stay updated with ";
$description = 'Stay updated with ';
foreach ($top_rss_keywords as $rss_keyword)
{
$description .= ", " . $rss_keyword->value;
foreach ($top_rss_keywords as $rss_keyword) {
$description .= ', '.$rss_keyword->value;
}
$description .= " and 1000+ other news " . strtolower($category->name) . " with 1-minute news bites with FutureWalker.";
$description .= ' and 1000+ other news '.strtolower($category->name).' with 1-minute news bites with FutureWalker.';
SEOTools::metatags();
SEOTools::twitter();

View File

@@ -1 +1 @@
import{_ as i}from"./vue-1b15f6c7.js";const n={name:"LqipLoader",mounted(){this.initLqipLoading()},methods:{initLqipLoading(){const e=document.getElementsByTagName("img");for(let t=0;t<e.length;t++)e[t].getAttribute("data-src")&&(e[t].onload=function(){this.classList.remove("lqip-blur")},e[t].setAttribute("src",e[t].getAttribute("data-src")))}}};function o(e,t,r,s,a,c){return null}const m=i(n,[["render",o]]);export{m as default};
import{_ as i}from"./vue-4ae8bf2c.js";const n={name:"LqipLoader",mounted(){this.initLqipLoading()},methods:{initLqipLoading(){const e=document.getElementsByTagName("img");for(let t=0;t<e.length;t++)e[t].getAttribute("data-src")&&(e[t].onload=function(){this.classList.remove("lqip-blur")},e[t].setAttribute("src",e[t].getAttribute("data-src")))}}};function o(e,t,r,s,a,c){return null}const m=i(n,[["render",o]]);export{m as default};

View File

@@ -0,0 +1 @@
import{_ as u,l as p,c as r,i as e,j as c,o as n,k as _,m}from"./vue-4ae8bf2c.js";const b={name:"ShareToFriends",data(){return{showModal:!1,shareUrl:null}},methods:{handleShareButton(){if(navigator.share){const o=document.title,t=document.querySelector('meta[name="description"]'),d=t?"Check this out: "+t.content:"",i=o||"FutureWalker",s=d||"Check this AI & tech news platform out!";navigator.share({title:i,text:s,url:this.shareUrl}).then(()=>{}).catch(a=>{this.showModal=!0})}else this.showModal=!0;this.showModal=!0},copyLink(){navigator.clipboard.writeText(this.shareUrl).then(()=>{p("Copied!",{position:"bottom-center",type:"success",timeout:1500,closeOnClick:!0,pauseOnFocusLoss:!0,pauseOnHover:!0,draggable:!0,draggablePercent:.6,showCloseButtonOnHover:!1,hideProgressBar:!1,closeButton:!0,icon:!0,rtl:!1})}).catch(o=>{})}},mounted(){this.shareUrl=window.location.href}},h=o=>(_("data-v-d913a747"),o=o(),m(),o),f=h(()=>e("i",{class:"bi bi-share-fill"},null,-1)),y=[f],g={key:0,class:"modal fade show",id:"shareModal",tabindex:"-1","aria-labelledby":"shareModalLabel",style:{display:"block"},"aria-modal":"true",role:"dialog"},k={class:"modal-dialog modal-dialog-centered"},v={class:"modal-content"},w={class:"modal-header"},x=h(()=>e("h1",{class:"modal-title fs-5 text-black fw-bold",id:"shareModalLabel"}," Share to Friends ",-1)),S={class:"modal-body d-grid gap-2"},C=["value"],M={key:1,class:"modal-backdrop fade show"};function B(o,t,d,i,s,a){return n(),r("div",null,[e("button",{type:"button",class:"align-self-center btn btn-outline-light ms-2",onClick:t[0]||(t[0]=(...l)=>a.handleShareButton&&a.handleShareButton(...l))},y),s.showModal?(n(),r("div",g,[e("div",k,[e("div",v,[e("div",w,[x,e("button",{type:"button",class:"btn-close",onClick:t[1]||(t[1]=l=>s.showModal=!1),"aria-label":"Close"})]),e("div",S,[e("input",{type:"text",readonly:"",class:"form-control",value:s.shareUrl},null,8,C),e("button",{class:"btn btn-primary w-full",onClick:t[2]||(t[2]=(...l)=>a.copyLink&&a.copyLink(...l))}," Copy Link ")])])])])):c("",!0),s.showModal?(n(),r("div",M)):c("",!0)])}const T=u(b,[["render",B],["__scopeId","data-v-d913a747"]]);export{T as default};

Binary file not shown.

View File

@@ -1 +1 @@
import{_ as o,o as p,c,a as r,b as u,p as i,d as m,e as g,f as _,g as d,v as f,Z as n,h as l}from"./vue-1b15f6c7.js";const A={name:"AppAuth"};function $(s,a,t,Z,w,x){return p(),c("div")}const h=o(A,[["render",$]]),e=r({AppAuth:h}),v=Object.assign({});e.use(u());e.use(i,m);e.use(g);e.use(_);e.use(d);e.use(f.ZiggyVue,n);window.Ziggy=n;Object.entries({...v}).forEach(([s,a])=>{const t=s.split("/").pop().replace(/\.\w+$/,"").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();e.component(t,l(a))});e.mount("#app");
import{_ as o,o as p,c,a as r,b as u,p as i,d as m,e as g,f as _,g as d,v as f,Z as n,h as l}from"./vue-4ae8bf2c.js";const A={name:"AppAuth"};function $(s,a,t,Z,w,x){return p(),c("div")}const h=o(A,[["render",$]]),e=r({AppAuth:h}),v=Object.assign({});e.use(u());e.use(i,m);e.use(g);e.use(_);e.use(d);e.use(f.ZiggyVue,n);window.Ziggy=n;Object.entries({...v}).forEach(([s,a])=>{const t=s.split("/").pop().replace(/\.\w+$/,"").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();e.component(t,l(a))});e.mount("#app");

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1,9 +1,9 @@
{
"_vue-1b15f6c7.js": {
"_vue-4ae8bf2c.js": {
"css": [
"assets/vue-935fc652.css"
],
"file": "assets/vue-1b15f6c7.js"
"file": "assets/vue-4ae8bf2c.js"
},
"node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff": {
"file": "assets/bootstrap-icons-4d4572ef.woff",
@@ -178,32 +178,48 @@
"src": "resources/images/tints/tint-9.png"
},
"resources/js/app-auth.js": {
"file": "assets/app-auth-25a86e45.js",
"file": "assets/app-auth-21f7e445.js",
"imports": [
"_vue-1b15f6c7.js"
"_vue-4ae8bf2c.js"
],
"isEntry": true,
"src": "resources/js/app-auth.js"
},
"resources/js/app-front.js": {
"dynamicImports": [
"resources/js/vue/front/LqipLoader.vue"
"resources/js/vue/front/LqipLoader.vue",
"resources/js/vue/front/ShareToFriends.vue"
],
"file": "assets/app-front-3e4d9dac.js",
"file": "assets/app-front-78ecf9bd.js",
"imports": [
"_vue-1b15f6c7.js"
"_vue-4ae8bf2c.js"
],
"isEntry": true,
"src": "resources/js/app-front.js"
},
"resources/js/vue/front/LqipLoader.vue": {
"file": "assets/LqipLoader-5f2dcf6c.js",
"file": "assets/LqipLoader-63085cd5.js",
"imports": [
"_vue-1b15f6c7.js"
"_vue-4ae8bf2c.js"
],
"isDynamicEntry": true,
"src": "resources/js/vue/front/LqipLoader.vue"
},
"resources/js/vue/front/ShareToFriends.css": {
"file": "assets/ShareToFriends-e3b0c442.css",
"src": "resources/js/vue/front/ShareToFriends.css"
},
"resources/js/vue/front/ShareToFriends.vue": {
"css": [
"assets/ShareToFriends-e3b0c442.css"
],
"file": "assets/ShareToFriends-5cbb942f.js",
"imports": [
"_vue-4ae8bf2c.js"
],
"isDynamicEntry": true,
"src": "resources/js/vue/front/ShareToFriends.vue"
},
"resources/sass/app-auth.scss": {
"file": "assets/app-auth-38851d9d.css",
"isEntry": true,

Binary file not shown.

View File

@@ -0,0 +1,134 @@
<template>
<div>
<button
type="button"
class="align-self-center btn btn-outline-light ms-2"
@click="handleShareButton"
>
<i class="bi bi-share-fill"></i>
</button>
<!-- Modal -->
<div
v-if="showModal"
class="modal fade show"
id="shareModal"
tabindex="-1"
aria-labelledby="shareModalLabel"
style="display: block"
aria-modal="true"
role="dialog"
>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h1
class="modal-title fs-5 text-black fw-bold"
id="shareModalLabel"
>
Share to Friends
</h1>
<button
type="button"
class="btn-close"
@click="showModal = false"
aria-label="Close"
></button>
</div>
<div class="modal-body d-grid gap-2">
<input
type="text"
readonly
class="form-control"
:value="shareUrl"
/>
<button class="btn btn-primary w-full" @click="copyLink">
Copy Link
</button>
</div>
</div>
</div>
</div>
<div v-if="showModal" class="modal-backdrop fade show"></div>
</div>
</template>
<script>
import { toast } from "vue3-toastify";
export default {
name: "ShareToFriends",
data() {
return {
showModal: false,
shareUrl: null,
};
},
methods: {
handleShareButton() {
if (navigator.share) {
// Extracting the HTML title
const shareTitle = document.title;
// Extracting the meta description
const metaDescriptionTag = document.querySelector(
'meta[name="description"]',
);
const shareText = metaDescriptionTag
? "Check this out: " + metaDescriptionTag.content
: "";
// Setting default values if not found
const title = shareTitle || "FutureWalker";
const text = shareText || "Check this AI & tech news platform out!";
navigator
.share({
title: title,
text: text,
url: this.shareUrl,
})
.then(() => console.log("Successful share"))
.catch((error) => {
this.showModal = true;
});
} else {
this.showModal = true;
}
this.showModal = true;
},
copyLink() {
navigator.clipboard
.writeText(this.shareUrl)
.then(() => {
toast("Copied!", {
position: "bottom-center",
type: "success",
timeout: 1500,
closeOnClick: true,
pauseOnFocusLoss: true,
pauseOnHover: true,
draggable: true,
draggablePercent: 0.6,
showCloseButtonOnHover: false,
hideProgressBar: false,
closeButton: true,
icon: true,
rtl: false,
});
})
.catch((err) => {
// Handle error
console.error("Error copying text: ", err);
});
},
},
mounted() {
this.shareUrl = window.location.href;
},
};
</script>
<style scoped>
/* Add any component-specific styles here */
</style>

View File

@@ -26,11 +26,13 @@
</a>
</div>
<div class="text-center text-md-end">
<div class="d-flex d-justify-content-end">
<div class="align-self-center d-none d-md-block">Important news shaping the digital future</div>
<div class="d-block d-md-none" style="width:51px; height: 38px;"></div>
<share-to-friends></share-to-friends>
</div>
<div class="col-12 col-md-7 col-lg-8 text-center text-md-end d-none d-md-block">
<div>Important news shaping the digital future</div>
</div>
</div>
</header>

View File

@@ -22,5 +22,7 @@
--}}
<div class="w-full text-center text-secondary">
<small class="text-center">AI & tech news syndication site built by <a href="https://x.com/charlestehio">@charlestehio</a>. All trademarks are the property of their respective owners.</small>
<small class="text-center">AI & tech news syndication site built by <a
href="https://x.com/charlestehio">@charlestehio</a>. All trademarks are the property of their respective
owners.</small>
</div>

View File

@@ -43,8 +43,7 @@
$rss_url = $request->input('rss_url');
if (is_empty($rss_url))
{
if (is_empty($rss_url)) {
return abort(404);
}
@@ -52,7 +51,6 @@
});
Route::get('/crawlTask', [App\Http\Controllers\Tests\TestController::class, 'crawlTask']);
Route::get('/set_keywords', function (Request $request) {