@liberfi.io/ui-media-track 0.1.286 → 0.1.288

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,6 +16,8 @@ declare class MediaTrackClient implements IMediaTrackClient {
16
16
  private streamEndpoint;
17
17
  private accessToken;
18
18
  private initPromise;
19
+ private connectionGeneration;
20
+ private connectionRequested;
19
21
  private static get isServer();
20
22
  constructor({ endpoint, streamEndpoint, accessToken, }: MediaTrackClientOptions);
21
23
  private initClient;
@@ -16,6 +16,8 @@ declare class MediaTrackClient implements IMediaTrackClient {
16
16
  private streamEndpoint;
17
17
  private accessToken;
18
18
  private initPromise;
19
+ private connectionGeneration;
20
+ private connectionRequested;
19
21
  private static get isServer();
20
22
  constructor({ endpoint, streamEndpoint, accessToken, }: MediaTrackClientOptions);
21
23
  private initClient;
@@ -1,2 +1,2 @@
1
- 'use strict';var centrifuge=require('@chainstream-io/centrifuge'),utils=require('@liberfi.io/utils'),types=require('@liberfi.io/types');function o(e){return {id:e.i,type:"tweet",tokenType:e.tt,token:e.t?v(e.t):void 0,tweet:f(e.tw),sourceTweet:e.s?C(e.s):void 0}}function u(e){return e==="sol"?types.Chain.SOLANA:utils.chainIdBySlug(e)}function v(e){let t=u(e.c);return t?d(e,t):void 0}function G(e){let t=u(e.c);if(!t)throw new Error(`Unsupported chain: ${e.c}`);return d(e,t)}function d(e,t){let i=e.p&&e.p1&&new utils.SafeBigNumber(e.p1).isPositive()?new utils.SafeBigNumber(e.p).minus(e.p1).div(e.p1).times(100).toString():void 0;return {chain:t,address:e.a,symbol:e.s,image:e.i,latestPrice:e.p,previousPrice:e.p1,priceChange:i}}function f(e){return {tweetId:e.i,type:e.t,timestamp:Number(e.ts),user:b(e.u),content:p(e.c)}}function C(e){return {tweetId:e.i,user:b(e.u),content:p(e.c)}}function b(e){return {username:e.s,screenName:e.n,avatar:e.a,tags:e.ut}}function p(e){return {text:e.t,medias:e.m?e.m.map(y).filter(Boolean):void 0}}function y(e){return {type:e.t,url:e.u}}function T(e){return {symbol:e.ticker,name:e.coin_name,image:e.icon_url}}function w(e,t,i){if(e.type==="tweet")return I(e,t,i);throw new Error(`Unsupported media type: ${e.type}`)}function l(e){if(e.type==="tweet")return x(e);throw new Error(`Unsupported media type: ${e.type}`)}function x(e){return {tweet_id:e.tweet.tweetId,tweet_info:e.tweet.content.text}}function I(e,t,i){return {res_type:"tw",res_id:i?.sourceTweet?e.sourceTweet?.tweetId??e.id:e.id,source_lang:i?.sourceLanguage,target_lang:t,text:(i?.sourceTweet?e.sourceTweet?.content.text:e.tweet.content.text)??""}}var M=class e{client;listenersMap;endpoint;streamEndpoint;accessToken;initPromise=null;static get isServer(){return typeof window>"u"}constructor({endpoint:t,streamEndpoint:i,accessToken:n}){this.endpoint=t,this.streamEndpoint=i,this.accessToken=n,this.listenersMap=new Map,e.isServer||this.connect();}async initClient(){if(this.client)return;let t=await this.getTokenValue(),i=this.buildWsUrl(this.streamEndpoint,t);this.client=new centrifuge.Centrifuge(i,{getToken:async()=>this.getTokenValue()}),this.client.on("connected",()=>{console.info("[media-track] connected");}).on("disconnected",n=>{console.warn("[media-track] disconnected",n);}).on("error",n=>{console.error("[media-track] error: ",n);});}async getTokenValue(){return typeof this.accessToken=="string"?this.accessToken:await this.accessToken.getToken()}buildWsUrl(t,i){let n=new URL(t);return n.searchParams.set("token",i),n.toString()}async ensureInitialized(){e.isServer||(this.initPromise||this.connect(),await this.initPromise);}async translate(t,i,n){let r=await this._requestOptions(),s=w(t,i,n);return (await utils.httpPost(`${this.endpoint}/translation`,s,r)).data.target_text}connect(){e.isServer||(this.initPromise=this.initClient().then(()=>{this.client.connect();}));}disconnect(){this.client&&this.client.disconnect(),this.initPromise=null;}subscribe(t,i){let n=this.listenersMap.get(t);return n||(n=new Set,this.listenersMap.set(t,n)),n.add(i),this.ensureInitialized().then(()=>{this.client.getSubscription(t)||(console.info("[media-track] create new sub: ",t),this.client.newSubscription(t,{delta:"fossil"}).on("subscribed",()=>{console.info("[media-track] subscribed",t);}).on("unsubscribed",()=>{console.info("[media-track] unsubscribed",t);}).on("publication",s=>{this.listenersMap.get(t)?.forEach(S=>S(s.data));}).subscribe());}),new a(this,t,i)}unsubscribe(t,i){let n=this.listenersMap.get(t);if(n&&(n.delete(i),console.info(`[media-track] unsubscribe ${t} listener, remain: ${n.size}`),n.size===0)){console.info(`[media-track] unsubscribe channel: ${t}`);let r=this.client.getSubscription(t);r&&(r.unsubscribe(),this.client.removeSubscription(r)),this.listenersMap.delete(t);}}subscribeTweetMedia({callback:t}){return this.subscribe("x-monitor-basic",i=>{try{t(o(i));}catch(n){console.error("[media-track] subscribeTweetMedia error: ",n);}})}subscribeTweetMediaToken({callback:t}){return this.subscribe("x-monitor-token",i=>{try{t(o(i));}catch(n){console.error("[media-track] subscribeTweetMediaToken error: ",n);}})}async generateMeme(t){let i=await this._requestOptions(),n=l(t),r=await utils.httpPost(`${this.endpoint}/meme/generate`,n,i);return T(r.data)}async _requestOptions(){return {headers:{Authorization:`Bearer ${await this.getTokenValue()}`}}}},a=class{constructor(t,i,n){this.client=t;this.channel=i;this.fn=n;}unsubscribe(){this.client.unsubscribe(this.channel,this.fn);}};exports.MediaTrackClient=M;exports.convertFromGenerateMemeResult=T;exports.convertFromSubscribedMediaToken=G;exports.convertFromSubscribedSourceTweet=C;exports.convertFromSubscribedTweet=f;exports.convertFromSubscribedTweetContent=p;exports.convertFromSubscribedTweetContentMedia=y;exports.convertFromSubscribedTweetMedia=o;exports.convertFromSubscribedTweetUser=b;exports.toGenerateMemeParamsDTO=l;exports.toGenerateTweetMemeParamsDTO=x;exports.toTranslateParamsDTO=w;exports.toTranslateTweetParamsDTO=I;//# sourceMappingURL=index.js.map
1
+ 'use strict';var centrifuge=require('@chainstream-io/centrifuge'),utils=require('@liberfi.io/utils'),types=require('@liberfi.io/types');function o(e){return {id:e.i,type:"tweet",tokenType:e.tt,token:e.t?v(e.t):void 0,tweet:C(e.tw),sourceTweet:e.s?y(e.s):void 0}}function u(e){return e==="sol"?types.Chain.SOLANA:utils.chainIdBySlug(e)}function v(e){let t=u(e.c);return t?d(e,t):void 0}function q(e){let t=u(e.c);if(!t)throw new Error(`Unsupported chain: ${e.c}`);return d(e,t)}function d(e,t){let n=e.p&&e.p1&&new utils.SafeBigNumber(e.p1).isPositive()?new utils.SafeBigNumber(e.p).minus(e.p1).div(e.p1).times(100).toString():void 0;return {chain:t,address:e.a,symbol:e.s,image:e.i,latestPrice:e.p,previousPrice:e.p1,priceChange:n}}function C(e){return {tweetId:e.i,type:e.t,timestamp:Number(e.ts),user:b(e.u),content:p(e.c)}}function y(e){return {tweetId:e.i,user:b(e.u),content:p(e.c)}}function b(e){return {username:e.s,screenName:e.n,avatar:e.a,tags:e.ut}}function p(e){return {text:e.t,medias:e.m?e.m.map(x).filter(Boolean):void 0}}function x(e){return {type:e.t,url:e.u}}function T(e){return {symbol:e.ticker,name:e.coin_name,image:e.icon_url}}function l(e,t,n){if(e.type==="tweet")return P(e,t,n);throw new Error(`Unsupported media type: ${e.type}`)}function w(e){if(e.type==="tweet")return I(e);throw new Error(`Unsupported media type: ${e.type}`)}function I(e){return {tweet_id:e.tweet.tweetId,tweet_info:e.tweet.content.text}}function P(e,t,n){return {res_type:"tw",res_id:n?.sourceTweet?e.sourceTweet?.tweetId??e.id:e.id,source_lang:n?.sourceLanguage,target_lang:t,text:(n?.sourceTweet?e.sourceTweet?.content.text:e.tweet.content.text)??""}}var M=class e{client;listenersMap;endpoint;streamEndpoint;accessToken;initPromise=null;connectionGeneration=0;connectionRequested=false;static get isServer(){return typeof window>"u"}constructor({endpoint:t,streamEndpoint:n,accessToken:i}){this.endpoint=t,this.streamEndpoint=n,this.accessToken=i,this.listenersMap=new Map;}async initClient(t){if(this.client)return this.client;let n=await this.getTokenValue();if(t!==this.connectionGeneration)return;let i=this.buildWsUrl(this.streamEndpoint,n),r=new centrifuge.Centrifuge(i,{getToken:async()=>this.getTokenValue()});return r.on("connected",()=>{console.info("[media-track] connected");}).on("disconnected",s=>{console.warn("[media-track] disconnected",s);}).on("error",s=>{console.error("[media-track] error: ",s);}),this.client=r,r}async getTokenValue(){return typeof this.accessToken=="string"?this.accessToken:await this.accessToken.getToken()}buildWsUrl(t,n){let i=new URL(t);return i.searchParams.set("token",n),i.toString()}async ensureInitialized(){e.isServer||(this.connectionRequested||this.connect(),await this.initPromise);}async translate(t,n,i){let r=await this._requestOptions(),s=l(t,n,i);return (await utils.httpPost(`${this.endpoint}/translation`,s,r)).data.target_text}connect(){if(e.isServer||this.connectionRequested)return;this.connectionRequested=true;let t=++this.connectionGeneration;this.initPromise=this.initClient(t).then(n=>{t===this.connectionGeneration&&n?.connect();});}disconnect(){this.connectionRequested=false,this.connectionGeneration+=1,this.client?.disconnect(),this.client=void 0,this.initPromise=null;}subscribe(t,n){let i=this.listenersMap.get(t);return i||(i=new Set,this.listenersMap.set(t,i)),i.add(n),this.ensureInitialized().then(()=>{let r=this.listenersMap.get(t),s=this.client;!r?.has(n)||!s||s.getSubscription(t)||(console.info("[media-track] create new sub: ",t),s.newSubscription(t,{delta:"fossil"}).on("subscribed",()=>{console.info("[media-track] subscribed",t);}).on("unsubscribed",()=>{console.info("[media-track] unsubscribed",t);}).on("publication",g=>{this.listenersMap.get(t)?.forEach(S=>S(g.data));}).subscribe());}),new a(this,t,n)}unsubscribe(t,n){let i=this.listenersMap.get(t);if(i&&(i.delete(n),console.info(`[media-track] unsubscribe ${t} listener, remain: ${i.size}`),i.size===0)){console.info(`[media-track] unsubscribe channel: ${t}`);let r=this.client?.getSubscription(t);r&&(r.unsubscribe(),this.client?.removeSubscription(r)),this.listenersMap.delete(t);}}subscribeTweetMedia({callback:t}){return this.subscribe("x-monitor-basic",n=>{try{t(o(n));}catch(i){console.error("[media-track] subscribeTweetMedia error: ",i);}})}subscribeTweetMediaToken({callback:t}){return this.subscribe("x-monitor-token",n=>{try{t(o(n));}catch(i){console.error("[media-track] subscribeTweetMediaToken error: ",i);}})}async generateMeme(t){let n=await this._requestOptions(),i=w(t),r=await utils.httpPost(`${this.endpoint}/meme/generate`,i,n);return T(r.data)}async _requestOptions(){return {headers:{Authorization:`Bearer ${await this.getTokenValue()}`}}}},a=class{constructor(t,n,i){this.client=t;this.channel=n;this.fn=i;}unsubscribe(){this.client.unsubscribe(this.channel,this.fn);}};exports.MediaTrackClient=M;exports.convertFromGenerateMemeResult=T;exports.convertFromSubscribedMediaToken=q;exports.convertFromSubscribedSourceTweet=y;exports.convertFromSubscribedTweet=C;exports.convertFromSubscribedTweetContent=p;exports.convertFromSubscribedTweetContentMedia=x;exports.convertFromSubscribedTweetMedia=o;exports.convertFromSubscribedTweetUser=b;exports.toGenerateMemeParamsDTO=w;exports.toGenerateTweetMemeParamsDTO=I;exports.toTranslateParamsDTO=l;exports.toTranslateTweetParamsDTO=P;//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/utils.ts","../../src/client/client.ts"],"names":["convertFromSubscribedTweetMedia","from","tryConvertFromSubscribedMediaToken","convertFromSubscribedTweet","convertFromSubscribedSourceTweet","resolveSubscribedMediaTokenChain","slug","Chain","chainIdBySlug","chain","createMediaToken","convertFromSubscribedMediaToken","priceChange","SafeBigNumber","convertFromSubscribedTweetUser","convertFromSubscribedTweetContent","convertFromSubscribedTweetContentMedia","convertFromGenerateMemeResult","toTranslateParamsDTO","media","targetLanguage","options","toTranslateTweetParamsDTO","toGenerateMemeParamsDTO","toGenerateTweetMemeParamsDTO","MediaTrackClient","_MediaTrackClient","endpoint","streamEndpoint","accessToken","token","wsUrl","Centrifuge","err","url","requestOptions","params","httpPost","channel","fn","listeners","ctx","it","Subscription","sub","callback","data","error","res","client"],"mappings":"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","file":"index.js","sourcesContent":["import { LocaleCode } from \"@liberfi.io/i18n\";\nimport { Chain } from \"@liberfi.io/types\";\nimport { chainIdBySlug, SafeBigNumber } from \"@liberfi.io/utils\";\nimport {\n GeneratedMemeInfo,\n IMedia,\n MediaToken,\n SourceTweet,\n Tweet,\n TweetContent,\n TweetContentMedia,\n TweetMedia,\n TweetUser,\n} from \"../types\";\nimport {\n GenerateMemeResult,\n SubscribedMediaToken,\n SubscribedSourceTweet,\n SubscribedTweet,\n SubscribedTweetContent,\n SubscribedTweetContentMedia,\n SubscribedTweetMedia,\n SubscribedTweetUser,\n TranslateTweetRequest,\n} from \"./types\";\n\nexport function convertFromSubscribedTweetMedia(\n from: SubscribedTweetMedia,\n): TweetMedia {\n return {\n id: from.i,\n type: \"tweet\",\n tokenType: from.tt,\n // Token metadata is optional enrichment; an unknown chain must not drop the tweet.\n token: from.t ? tryConvertFromSubscribedMediaToken(from.t) : undefined,\n tweet: convertFromSubscribedTweet(from.tw),\n sourceTweet: from.s ? convertFromSubscribedSourceTweet(from.s) : undefined,\n };\n}\n\nfunction resolveSubscribedMediaTokenChain(slug: string): Chain | undefined {\n return slug === \"sol\" ? Chain.SOLANA : chainIdBySlug(slug);\n}\n\nfunction tryConvertFromSubscribedMediaToken(\n from: SubscribedMediaToken,\n): MediaToken | undefined {\n const chain = resolveSubscribedMediaTokenChain(from.c);\n return chain ? createMediaToken(from, chain) : undefined;\n}\n\nexport function convertFromSubscribedMediaToken(\n from: SubscribedMediaToken,\n): MediaToken {\n const chain = resolveSubscribedMediaTokenChain(from.c);\n if (!chain) {\n throw new Error(`Unsupported chain: ${from.c}`);\n }\n return createMediaToken(from, chain);\n}\n\nfunction createMediaToken(\n from: SubscribedMediaToken,\n chain: Chain,\n): MediaToken {\n const priceChange =\n from.p && from.p1 && new SafeBigNumber(from.p1).isPositive()\n ? new SafeBigNumber(from.p)\n .minus(from.p1)\n .div(from.p1)\n .times(100)\n .toString()\n : undefined;\n return {\n chain,\n address: from.a,\n symbol: from.s,\n image: from.i,\n latestPrice: from.p,\n previousPrice: from.p1,\n priceChange,\n };\n}\n\nexport function convertFromSubscribedTweet(from: SubscribedTweet): Tweet {\n return {\n tweetId: from.i,\n type: from.t,\n timestamp: Number(from.ts),\n user: convertFromSubscribedTweetUser(from.u),\n content: convertFromSubscribedTweetContent(from.c),\n };\n}\n\nexport function convertFromSubscribedSourceTweet(\n from: SubscribedSourceTweet,\n): SourceTweet {\n return {\n tweetId: from.i,\n user: convertFromSubscribedTweetUser(from.u),\n content: convertFromSubscribedTweetContent(from.c),\n };\n}\n\nexport function convertFromSubscribedTweetUser(\n from: SubscribedTweetUser,\n): TweetUser {\n return {\n username: from.s,\n screenName: from.n,\n avatar: from.a,\n tags: from.ut,\n };\n}\n\nexport function convertFromSubscribedTweetContent(\n from: SubscribedTweetContent,\n): TweetContent {\n return {\n text: from.t,\n medias: from.m\n ? from.m.map(convertFromSubscribedTweetContentMedia).filter(Boolean)\n : undefined,\n };\n}\n\nexport function convertFromSubscribedTweetContentMedia(\n from: SubscribedTweetContentMedia,\n): TweetContentMedia {\n return {\n type: from.t,\n url: from.u,\n };\n}\n\nexport function convertFromGenerateMemeResult(\n from: GenerateMemeResult,\n): GeneratedMemeInfo {\n return {\n symbol: from.ticker,\n name: from.coin_name,\n image: from.icon_url,\n };\n}\n\nexport function toTranslateParamsDTO(\n media: IMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n): TranslateTweetRequest {\n switch (media.type) {\n case \"tweet\":\n return toTranslateTweetParamsDTO(\n media as TweetMedia,\n targetLanguage,\n options,\n );\n default:\n throw new Error(`Unsupported media type: ${media.type}`);\n }\n}\n\nexport function toGenerateMemeParamsDTO(media: IMedia) {\n switch (media.type) {\n case \"tweet\":\n return toGenerateTweetMemeParamsDTO(media as TweetMedia);\n default:\n throw new Error(`Unsupported media type: ${media.type}`);\n }\n}\n\nexport function toGenerateTweetMemeParamsDTO(media: TweetMedia) {\n return {\n tweet_id: media.tweet.tweetId,\n tweet_info: media.tweet.content.text,\n };\n}\n\nexport function toTranslateTweetParamsDTO(\n media: TweetMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n): TranslateTweetRequest {\n return {\n res_type: \"tw\",\n res_id: options?.sourceTweet\n ? (media.sourceTweet?.tweetId ?? media.id)\n : media.id,\n source_lang: options?.sourceLanguage,\n target_lang: targetLanguage,\n text:\n (options?.sourceTweet\n ? media.sourceTweet?.content.text\n : media.tweet.content.text) ?? \"\",\n };\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable no-console */\nimport { Centrifuge } from \"@chainstream-io/centrifuge\";\nimport { LocaleCode } from \"@liberfi.io/i18n\";\nimport { ISubscription } from \"@liberfi.io/types\";\nimport { httpPost } from \"@liberfi.io/utils\";\nimport {\n GeneratedMemeInfo,\n IMedia,\n IMediaTrackClient,\n SubscribeTweetMediasOptions,\n} from \"../types\";\nimport {\n GenerateMemeResponse,\n SubscribedTweetMedia,\n TranslateTweetResponse,\n} from \"./types\";\nimport {\n convertFromGenerateMemeResult,\n convertFromSubscribedTweetMedia,\n toGenerateMemeParamsDTO,\n toTranslateParamsDTO,\n} from \"./utils\";\n\nexport interface MediaTrackClientOptions {\n endpoint: string;\n streamEndpoint: string;\n accessToken:\n | string\n | {\n getToken(): Promise<string> | string;\n };\n}\n\nexport class MediaTrackClient implements IMediaTrackClient {\n private client!: Centrifuge;\n private listenersMap: Map<string, Set<(data: any) => void>>;\n private endpoint: string;\n private streamEndpoint: string;\n private accessToken: MediaTrackClientOptions[\"accessToken\"];\n private initPromise: Promise<void> | null = null;\n\n private static get isServer(): boolean {\n return typeof window === \"undefined\";\n }\n\n constructor({\n endpoint,\n streamEndpoint,\n accessToken,\n }: MediaTrackClientOptions) {\n this.endpoint = endpoint;\n this.streamEndpoint = streamEndpoint;\n this.accessToken = accessToken;\n this.listenersMap = new Map();\n\n if (!MediaTrackClient.isServer) {\n this.connect();\n }\n }\n\n private async initClient() {\n if (this.client) {\n return;\n }\n const token = await this.getTokenValue();\n const wsUrl = this.buildWsUrl(this.streamEndpoint, token);\n this.client = new Centrifuge(wsUrl, {\n getToken: async () => {\n return this.getTokenValue();\n },\n });\n\n this.client\n .on(\"connected\", () => {\n console.info(\"[media-track] connected\");\n })\n .on(\"disconnected\", (err) => {\n console.warn(\"[media-track] disconnected\", err);\n })\n .on(\"error\", (err) => {\n console.error(\"[media-track] error: \", err);\n });\n }\n\n private async getTokenValue(): Promise<string> {\n return typeof this.accessToken === \"string\"\n ? this.accessToken\n : await this.accessToken.getToken();\n }\n\n private buildWsUrl(endpoint: string, token: string): string {\n const url = new URL(endpoint);\n url.searchParams.set(\"token\", token);\n return url.toString();\n }\n\n private async ensureInitialized() {\n if (MediaTrackClient.isServer) return;\n if (!this.initPromise) {\n this.connect();\n }\n await this.initPromise;\n }\n\n async translate(\n media: IMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n ): Promise<string> {\n const requestOptions = await this._requestOptions();\n const params = toTranslateParamsDTO(media, targetLanguage, options);\n const res = await httpPost<TranslateTweetResponse>(\n `${this.endpoint}/translation`,\n params,\n requestOptions,\n );\n return res.data.target_text;\n }\n\n /**\n * Connect to the media track realtime server.\n * Lazily initializes the Centrifuge client on first call.\n * No-op when called during SSR (Node.js).\n */\n connect() {\n if (MediaTrackClient.isServer) return;\n this.initPromise = this.initClient().then(() => {\n this.client.connect();\n });\n }\n\n /**\n * Disconnect and release the underlying Centrifuge transport.\n */\n disconnect() {\n if (this.client) {\n this.client.disconnect();\n }\n this.initPromise = null;\n }\n\n subscribe<T = any>(channel: string, fn: (data: T) => void): ISubscription {\n let listeners = this.listenersMap.get(channel);\n if (!listeners) {\n listeners = new Set();\n this.listenersMap.set(channel, listeners);\n }\n listeners.add(fn);\n\n void this.ensureInitialized().then(() => {\n if (!this.client.getSubscription(channel)) {\n console.info(\"[media-track] create new sub: \", channel);\n\n const sub = this.client.newSubscription(channel, {\n delta: \"fossil\",\n });\n\n sub\n .on(\"subscribed\", () => {\n console.info(\"[media-track] subscribed\", channel);\n })\n .on(\"unsubscribed\", () => {\n console.info(\"[media-track] unsubscribed\", channel);\n })\n .on(\"publication\", (ctx) => {\n const ls = this.listenersMap.get(channel);\n ls?.forEach((it) => it(ctx.data));\n })\n .subscribe();\n }\n });\n\n return new Subscription<T>(this, channel, fn);\n }\n\n unsubscribe<T = any>(channel: string, fn: (data: T) => void) {\n const listeners = this.listenersMap.get(channel);\n if (!listeners) return;\n\n listeners.delete(fn);\n console.info(\n `[media-track] unsubscribe ${channel} listener, remain: ${listeners.size}`,\n );\n\n if (listeners.size === 0) {\n console.info(`[media-track] unsubscribe channel: ${channel}`);\n\n const sub = this.client.getSubscription(channel);\n if (sub) {\n sub.unsubscribe();\n this.client.removeSubscription(sub);\n }\n\n this.listenersMap.delete(channel);\n }\n }\n\n subscribeTweetMedia({\n callback,\n }: SubscribeTweetMediasOptions): ISubscription {\n return this.subscribe(\"x-monitor-basic\", (data: SubscribedTweetMedia) => {\n try {\n callback(convertFromSubscribedTweetMedia(data));\n } catch (error) {\n console.error(\"[media-track] subscribeTweetMedia error: \", error);\n }\n });\n }\n\n subscribeTweetMediaToken({\n callback,\n }: SubscribeTweetMediasOptions): ISubscription {\n return this.subscribe(\"x-monitor-token\", (data: SubscribedTweetMedia) => {\n try {\n callback(convertFromSubscribedTweetMedia(data));\n } catch (error) {\n console.error(\"[media-track] subscribeTweetMediaToken error: \", error);\n }\n });\n }\n\n async generateMeme(media: IMedia): Promise<GeneratedMemeInfo> {\n const requestOptions = await this._requestOptions();\n const params = toGenerateMemeParamsDTO(media);\n const res = await httpPost<GenerateMemeResponse>(\n `${this.endpoint}/meme/generate`,\n params,\n requestOptions,\n );\n return convertFromGenerateMemeResult(res.data);\n }\n\n async _requestOptions(): Promise<Omit<RequestInit, \"method\">> {\n const token = await this.getTokenValue();\n return {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n };\n }\n}\n\nclass Subscription<T> {\n constructor(\n private readonly client: MediaTrackClient,\n private readonly channel: string,\n private readonly fn: (data: T) => void,\n ) {}\n\n unsubscribe() {\n this.client.unsubscribe(this.channel, this.fn);\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/client/utils.ts","../../src/client/client.ts"],"names":["convertFromSubscribedTweetMedia","from","tryConvertFromSubscribedMediaToken","convertFromSubscribedTweet","convertFromSubscribedSourceTweet","resolveSubscribedMediaTokenChain","slug","Chain","chainIdBySlug","chain","createMediaToken","convertFromSubscribedMediaToken","priceChange","SafeBigNumber","convertFromSubscribedTweetUser","convertFromSubscribedTweetContent","convertFromSubscribedTweetContentMedia","convertFromGenerateMemeResult","toTranslateParamsDTO","media","targetLanguage","options","toTranslateTweetParamsDTO","toGenerateMemeParamsDTO","toGenerateTweetMemeParamsDTO","MediaTrackClient","_MediaTrackClient","endpoint","streamEndpoint","accessToken","generation","token","wsUrl","client","Centrifuge","err","url","requestOptions","params","httpPost","channel","fn","listeners","activeListeners","ctx","it","Subscription","sub","callback","data","error","res"],"mappings":"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","file":"index.js","sourcesContent":["import { LocaleCode } from \"@liberfi.io/i18n\";\nimport { Chain } from \"@liberfi.io/types\";\nimport { chainIdBySlug, SafeBigNumber } from \"@liberfi.io/utils\";\nimport {\n GeneratedMemeInfo,\n IMedia,\n MediaToken,\n SourceTweet,\n Tweet,\n TweetContent,\n TweetContentMedia,\n TweetMedia,\n TweetUser,\n} from \"../types\";\nimport {\n GenerateMemeResult,\n SubscribedMediaToken,\n SubscribedSourceTweet,\n SubscribedTweet,\n SubscribedTweetContent,\n SubscribedTweetContentMedia,\n SubscribedTweetMedia,\n SubscribedTweetUser,\n TranslateTweetRequest,\n} from \"./types\";\n\nexport function convertFromSubscribedTweetMedia(\n from: SubscribedTweetMedia,\n): TweetMedia {\n return {\n id: from.i,\n type: \"tweet\",\n tokenType: from.tt,\n // Token metadata is optional enrichment; an unknown chain must not drop the tweet.\n token: from.t ? tryConvertFromSubscribedMediaToken(from.t) : undefined,\n tweet: convertFromSubscribedTweet(from.tw),\n sourceTweet: from.s ? convertFromSubscribedSourceTweet(from.s) : undefined,\n };\n}\n\nfunction resolveSubscribedMediaTokenChain(slug: string): Chain | undefined {\n return slug === \"sol\" ? Chain.SOLANA : chainIdBySlug(slug);\n}\n\nfunction tryConvertFromSubscribedMediaToken(\n from: SubscribedMediaToken,\n): MediaToken | undefined {\n const chain = resolveSubscribedMediaTokenChain(from.c);\n return chain ? createMediaToken(from, chain) : undefined;\n}\n\nexport function convertFromSubscribedMediaToken(\n from: SubscribedMediaToken,\n): MediaToken {\n const chain = resolveSubscribedMediaTokenChain(from.c);\n if (!chain) {\n throw new Error(`Unsupported chain: ${from.c}`);\n }\n return createMediaToken(from, chain);\n}\n\nfunction createMediaToken(\n from: SubscribedMediaToken,\n chain: Chain,\n): MediaToken {\n const priceChange =\n from.p && from.p1 && new SafeBigNumber(from.p1).isPositive()\n ? new SafeBigNumber(from.p)\n .minus(from.p1)\n .div(from.p1)\n .times(100)\n .toString()\n : undefined;\n return {\n chain,\n address: from.a,\n symbol: from.s,\n image: from.i,\n latestPrice: from.p,\n previousPrice: from.p1,\n priceChange,\n };\n}\n\nexport function convertFromSubscribedTweet(from: SubscribedTweet): Tweet {\n return {\n tweetId: from.i,\n type: from.t,\n timestamp: Number(from.ts),\n user: convertFromSubscribedTweetUser(from.u),\n content: convertFromSubscribedTweetContent(from.c),\n };\n}\n\nexport function convertFromSubscribedSourceTweet(\n from: SubscribedSourceTweet,\n): SourceTweet {\n return {\n tweetId: from.i,\n user: convertFromSubscribedTweetUser(from.u),\n content: convertFromSubscribedTweetContent(from.c),\n };\n}\n\nexport function convertFromSubscribedTweetUser(\n from: SubscribedTweetUser,\n): TweetUser {\n return {\n username: from.s,\n screenName: from.n,\n avatar: from.a,\n tags: from.ut,\n };\n}\n\nexport function convertFromSubscribedTweetContent(\n from: SubscribedTweetContent,\n): TweetContent {\n return {\n text: from.t,\n medias: from.m\n ? from.m.map(convertFromSubscribedTweetContentMedia).filter(Boolean)\n : undefined,\n };\n}\n\nexport function convertFromSubscribedTweetContentMedia(\n from: SubscribedTweetContentMedia,\n): TweetContentMedia {\n return {\n type: from.t,\n url: from.u,\n };\n}\n\nexport function convertFromGenerateMemeResult(\n from: GenerateMemeResult,\n): GeneratedMemeInfo {\n return {\n symbol: from.ticker,\n name: from.coin_name,\n image: from.icon_url,\n };\n}\n\nexport function toTranslateParamsDTO(\n media: IMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n): TranslateTweetRequest {\n switch (media.type) {\n case \"tweet\":\n return toTranslateTweetParamsDTO(\n media as TweetMedia,\n targetLanguage,\n options,\n );\n default:\n throw new Error(`Unsupported media type: ${media.type}`);\n }\n}\n\nexport function toGenerateMemeParamsDTO(media: IMedia) {\n switch (media.type) {\n case \"tweet\":\n return toGenerateTweetMemeParamsDTO(media as TweetMedia);\n default:\n throw new Error(`Unsupported media type: ${media.type}`);\n }\n}\n\nexport function toGenerateTweetMemeParamsDTO(media: TweetMedia) {\n return {\n tweet_id: media.tweet.tweetId,\n tweet_info: media.tweet.content.text,\n };\n}\n\nexport function toTranslateTweetParamsDTO(\n media: TweetMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n): TranslateTweetRequest {\n return {\n res_type: \"tw\",\n res_id: options?.sourceTweet\n ? (media.sourceTweet?.tweetId ?? media.id)\n : media.id,\n source_lang: options?.sourceLanguage,\n target_lang: targetLanguage,\n text:\n (options?.sourceTweet\n ? media.sourceTweet?.content.text\n : media.tweet.content.text) ?? \"\",\n };\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable no-console */\nimport { Centrifuge } from \"@chainstream-io/centrifuge\";\nimport { LocaleCode } from \"@liberfi.io/i18n\";\nimport { ISubscription } from \"@liberfi.io/types\";\nimport { httpPost } from \"@liberfi.io/utils\";\nimport {\n GeneratedMemeInfo,\n IMedia,\n IMediaTrackClient,\n SubscribeTweetMediasOptions,\n} from \"../types\";\nimport {\n GenerateMemeResponse,\n SubscribedTweetMedia,\n TranslateTweetResponse,\n} from \"./types\";\nimport {\n convertFromGenerateMemeResult,\n convertFromSubscribedTweetMedia,\n toGenerateMemeParamsDTO,\n toTranslateParamsDTO,\n} from \"./utils\";\n\nexport interface MediaTrackClientOptions {\n endpoint: string;\n streamEndpoint: string;\n accessToken:\n | string\n | {\n getToken(): Promise<string> | string;\n };\n}\n\nexport class MediaTrackClient implements IMediaTrackClient {\n private client: Centrifuge | undefined;\n private listenersMap: Map<string, Set<(data: any) => void>>;\n private endpoint: string;\n private streamEndpoint: string;\n private accessToken: MediaTrackClientOptions[\"accessToken\"];\n private initPromise: Promise<void> | null = null;\n private connectionGeneration = 0;\n private connectionRequested = false;\n\n private static get isServer(): boolean {\n return typeof window === \"undefined\";\n }\n\n constructor({\n endpoint,\n streamEndpoint,\n accessToken,\n }: MediaTrackClientOptions) {\n this.endpoint = endpoint;\n this.streamEndpoint = streamEndpoint;\n this.accessToken = accessToken;\n this.listenersMap = new Map();\n }\n\n private async initClient(\n generation: number,\n ): Promise<Centrifuge | undefined> {\n if (this.client) {\n return this.client;\n }\n const token = await this.getTokenValue();\n if (generation !== this.connectionGeneration) {\n return undefined;\n }\n const wsUrl = this.buildWsUrl(this.streamEndpoint, token);\n const client = new Centrifuge(wsUrl, {\n getToken: async () => {\n return this.getTokenValue();\n },\n });\n\n client\n .on(\"connected\", () => {\n console.info(\"[media-track] connected\");\n })\n .on(\"disconnected\", (err) => {\n console.warn(\"[media-track] disconnected\", err);\n })\n .on(\"error\", (err) => {\n console.error(\"[media-track] error: \", err);\n });\n this.client = client;\n return client;\n }\n\n private async getTokenValue(): Promise<string> {\n return typeof this.accessToken === \"string\"\n ? this.accessToken\n : await this.accessToken.getToken();\n }\n\n private buildWsUrl(endpoint: string, token: string): string {\n const url = new URL(endpoint);\n url.searchParams.set(\"token\", token);\n return url.toString();\n }\n\n private async ensureInitialized() {\n if (MediaTrackClient.isServer) return;\n if (!this.connectionRequested) {\n this.connect();\n }\n await this.initPromise;\n }\n\n async translate(\n media: IMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n ): Promise<string> {\n const requestOptions = await this._requestOptions();\n const params = toTranslateParamsDTO(media, targetLanguage, options);\n const res = await httpPost<TranslateTweetResponse>(\n `${this.endpoint}/translation`,\n params,\n requestOptions,\n );\n return res.data.target_text;\n }\n\n /**\n * Connect to the media track realtime server.\n * Lazily initializes the Centrifuge client on first call.\n * No-op when called during SSR (Node.js).\n */\n connect() {\n if (MediaTrackClient.isServer || this.connectionRequested) return;\n this.connectionRequested = true;\n const generation = ++this.connectionGeneration;\n this.initPromise = this.initClient(generation).then((client) => {\n if (generation === this.connectionGeneration) {\n client?.connect();\n }\n });\n }\n\n /**\n * Disconnect and release the underlying Centrifuge transport.\n */\n disconnect() {\n this.connectionRequested = false;\n this.connectionGeneration += 1;\n this.client?.disconnect();\n this.client = undefined;\n this.initPromise = null;\n }\n\n subscribe<T = any>(channel: string, fn: (data: T) => void): ISubscription {\n let listeners = this.listenersMap.get(channel);\n if (!listeners) {\n listeners = new Set();\n this.listenersMap.set(channel, listeners);\n }\n listeners.add(fn);\n\n void this.ensureInitialized().then(() => {\n const activeListeners = this.listenersMap.get(channel);\n const client = this.client;\n if (!activeListeners?.has(fn) || !client) return;\n\n if (!client.getSubscription(channel)) {\n console.info(\"[media-track] create new sub: \", channel);\n\n const sub = client.newSubscription(channel, {\n delta: \"fossil\",\n });\n\n sub\n .on(\"subscribed\", () => {\n console.info(\"[media-track] subscribed\", channel);\n })\n .on(\"unsubscribed\", () => {\n console.info(\"[media-track] unsubscribed\", channel);\n })\n .on(\"publication\", (ctx) => {\n const ls = this.listenersMap.get(channel);\n ls?.forEach((it) => it(ctx.data));\n })\n .subscribe();\n }\n });\n\n return new Subscription<T>(this, channel, fn);\n }\n\n unsubscribe<T = any>(channel: string, fn: (data: T) => void) {\n const listeners = this.listenersMap.get(channel);\n if (!listeners) return;\n\n listeners.delete(fn);\n console.info(\n `[media-track] unsubscribe ${channel} listener, remain: ${listeners.size}`,\n );\n\n if (listeners.size === 0) {\n console.info(`[media-track] unsubscribe channel: ${channel}`);\n\n const sub = this.client?.getSubscription(channel);\n if (sub) {\n sub.unsubscribe();\n this.client?.removeSubscription(sub);\n }\n\n this.listenersMap.delete(channel);\n }\n }\n\n subscribeTweetMedia({\n callback,\n }: SubscribeTweetMediasOptions): ISubscription {\n return this.subscribe(\"x-monitor-basic\", (data: SubscribedTweetMedia) => {\n try {\n callback(convertFromSubscribedTweetMedia(data));\n } catch (error) {\n console.error(\"[media-track] subscribeTweetMedia error: \", error);\n }\n });\n }\n\n subscribeTweetMediaToken({\n callback,\n }: SubscribeTweetMediasOptions): ISubscription {\n return this.subscribe(\"x-monitor-token\", (data: SubscribedTweetMedia) => {\n try {\n callback(convertFromSubscribedTweetMedia(data));\n } catch (error) {\n console.error(\"[media-track] subscribeTweetMediaToken error: \", error);\n }\n });\n }\n\n async generateMeme(media: IMedia): Promise<GeneratedMemeInfo> {\n const requestOptions = await this._requestOptions();\n const params = toGenerateMemeParamsDTO(media);\n const res = await httpPost<GenerateMemeResponse>(\n `${this.endpoint}/meme/generate`,\n params,\n requestOptions,\n );\n return convertFromGenerateMemeResult(res.data);\n }\n\n async _requestOptions(): Promise<Omit<RequestInit, \"method\">> {\n const token = await this.getTokenValue();\n return {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n };\n }\n}\n\nclass Subscription<T> {\n constructor(\n private readonly client: MediaTrackClient,\n private readonly channel: string,\n private readonly fn: (data: T) => void,\n ) {}\n\n unsubscribe() {\n this.client.unsubscribe(this.channel, this.fn);\n }\n}\n"]}
@@ -1,2 +1,2 @@
1
- import {Centrifuge}from'@chainstream-io/centrifuge';import {SafeBigNumber,httpPost,chainIdBySlug}from'@liberfi.io/utils';import {Chain}from'@liberfi.io/types';function o(e){return {id:e.i,type:"tweet",tokenType:e.tt,token:e.t?v(e.t):void 0,tweet:f(e.tw),sourceTweet:e.s?C(e.s):void 0}}function u(e){return e==="sol"?Chain.SOLANA:chainIdBySlug(e)}function v(e){let t=u(e.c);return t?d(e,t):void 0}function G(e){let t=u(e.c);if(!t)throw new Error(`Unsupported chain: ${e.c}`);return d(e,t)}function d(e,t){let i=e.p&&e.p1&&new SafeBigNumber(e.p1).isPositive()?new SafeBigNumber(e.p).minus(e.p1).div(e.p1).times(100).toString():void 0;return {chain:t,address:e.a,symbol:e.s,image:e.i,latestPrice:e.p,previousPrice:e.p1,priceChange:i}}function f(e){return {tweetId:e.i,type:e.t,timestamp:Number(e.ts),user:b(e.u),content:p(e.c)}}function C(e){return {tweetId:e.i,user:b(e.u),content:p(e.c)}}function b(e){return {username:e.s,screenName:e.n,avatar:e.a,tags:e.ut}}function p(e){return {text:e.t,medias:e.m?e.m.map(y).filter(Boolean):void 0}}function y(e){return {type:e.t,url:e.u}}function T(e){return {symbol:e.ticker,name:e.coin_name,image:e.icon_url}}function w(e,t,i){if(e.type==="tweet")return I(e,t,i);throw new Error(`Unsupported media type: ${e.type}`)}function l(e){if(e.type==="tweet")return x(e);throw new Error(`Unsupported media type: ${e.type}`)}function x(e){return {tweet_id:e.tweet.tweetId,tweet_info:e.tweet.content.text}}function I(e,t,i){return {res_type:"tw",res_id:i?.sourceTweet?e.sourceTweet?.tweetId??e.id:e.id,source_lang:i?.sourceLanguage,target_lang:t,text:(i?.sourceTweet?e.sourceTweet?.content.text:e.tweet.content.text)??""}}var M=class e{client;listenersMap;endpoint;streamEndpoint;accessToken;initPromise=null;static get isServer(){return typeof window>"u"}constructor({endpoint:t,streamEndpoint:i,accessToken:n}){this.endpoint=t,this.streamEndpoint=i,this.accessToken=n,this.listenersMap=new Map,e.isServer||this.connect();}async initClient(){if(this.client)return;let t=await this.getTokenValue(),i=this.buildWsUrl(this.streamEndpoint,t);this.client=new Centrifuge(i,{getToken:async()=>this.getTokenValue()}),this.client.on("connected",()=>{console.info("[media-track] connected");}).on("disconnected",n=>{console.warn("[media-track] disconnected",n);}).on("error",n=>{console.error("[media-track] error: ",n);});}async getTokenValue(){return typeof this.accessToken=="string"?this.accessToken:await this.accessToken.getToken()}buildWsUrl(t,i){let n=new URL(t);return n.searchParams.set("token",i),n.toString()}async ensureInitialized(){e.isServer||(this.initPromise||this.connect(),await this.initPromise);}async translate(t,i,n){let r=await this._requestOptions(),s=w(t,i,n);return (await httpPost(`${this.endpoint}/translation`,s,r)).data.target_text}connect(){e.isServer||(this.initPromise=this.initClient().then(()=>{this.client.connect();}));}disconnect(){this.client&&this.client.disconnect(),this.initPromise=null;}subscribe(t,i){let n=this.listenersMap.get(t);return n||(n=new Set,this.listenersMap.set(t,n)),n.add(i),this.ensureInitialized().then(()=>{this.client.getSubscription(t)||(console.info("[media-track] create new sub: ",t),this.client.newSubscription(t,{delta:"fossil"}).on("subscribed",()=>{console.info("[media-track] subscribed",t);}).on("unsubscribed",()=>{console.info("[media-track] unsubscribed",t);}).on("publication",s=>{this.listenersMap.get(t)?.forEach(S=>S(s.data));}).subscribe());}),new a(this,t,i)}unsubscribe(t,i){let n=this.listenersMap.get(t);if(n&&(n.delete(i),console.info(`[media-track] unsubscribe ${t} listener, remain: ${n.size}`),n.size===0)){console.info(`[media-track] unsubscribe channel: ${t}`);let r=this.client.getSubscription(t);r&&(r.unsubscribe(),this.client.removeSubscription(r)),this.listenersMap.delete(t);}}subscribeTweetMedia({callback:t}){return this.subscribe("x-monitor-basic",i=>{try{t(o(i));}catch(n){console.error("[media-track] subscribeTweetMedia error: ",n);}})}subscribeTweetMediaToken({callback:t}){return this.subscribe("x-monitor-token",i=>{try{t(o(i));}catch(n){console.error("[media-track] subscribeTweetMediaToken error: ",n);}})}async generateMeme(t){let i=await this._requestOptions(),n=l(t),r=await httpPost(`${this.endpoint}/meme/generate`,n,i);return T(r.data)}async _requestOptions(){return {headers:{Authorization:`Bearer ${await this.getTokenValue()}`}}}},a=class{constructor(t,i,n){this.client=t;this.channel=i;this.fn=n;}unsubscribe(){this.client.unsubscribe(this.channel,this.fn);}};export{M as MediaTrackClient,T as convertFromGenerateMemeResult,G as convertFromSubscribedMediaToken,C as convertFromSubscribedSourceTweet,f as convertFromSubscribedTweet,p as convertFromSubscribedTweetContent,y as convertFromSubscribedTweetContentMedia,o as convertFromSubscribedTweetMedia,b as convertFromSubscribedTweetUser,l as toGenerateMemeParamsDTO,x as toGenerateTweetMemeParamsDTO,w as toTranslateParamsDTO,I as toTranslateTweetParamsDTO};//# sourceMappingURL=index.mjs.map
1
+ import {Centrifuge}from'@chainstream-io/centrifuge';import {SafeBigNumber,httpPost,chainIdBySlug}from'@liberfi.io/utils';import {Chain}from'@liberfi.io/types';function o(e){return {id:e.i,type:"tweet",tokenType:e.tt,token:e.t?v(e.t):void 0,tweet:C(e.tw),sourceTweet:e.s?y(e.s):void 0}}function u(e){return e==="sol"?Chain.SOLANA:chainIdBySlug(e)}function v(e){let t=u(e.c);return t?d(e,t):void 0}function q(e){let t=u(e.c);if(!t)throw new Error(`Unsupported chain: ${e.c}`);return d(e,t)}function d(e,t){let n=e.p&&e.p1&&new SafeBigNumber(e.p1).isPositive()?new SafeBigNumber(e.p).minus(e.p1).div(e.p1).times(100).toString():void 0;return {chain:t,address:e.a,symbol:e.s,image:e.i,latestPrice:e.p,previousPrice:e.p1,priceChange:n}}function C(e){return {tweetId:e.i,type:e.t,timestamp:Number(e.ts),user:b(e.u),content:p(e.c)}}function y(e){return {tweetId:e.i,user:b(e.u),content:p(e.c)}}function b(e){return {username:e.s,screenName:e.n,avatar:e.a,tags:e.ut}}function p(e){return {text:e.t,medias:e.m?e.m.map(x).filter(Boolean):void 0}}function x(e){return {type:e.t,url:e.u}}function T(e){return {symbol:e.ticker,name:e.coin_name,image:e.icon_url}}function l(e,t,n){if(e.type==="tweet")return P(e,t,n);throw new Error(`Unsupported media type: ${e.type}`)}function w(e){if(e.type==="tweet")return I(e);throw new Error(`Unsupported media type: ${e.type}`)}function I(e){return {tweet_id:e.tweet.tweetId,tweet_info:e.tweet.content.text}}function P(e,t,n){return {res_type:"tw",res_id:n?.sourceTweet?e.sourceTweet?.tweetId??e.id:e.id,source_lang:n?.sourceLanguage,target_lang:t,text:(n?.sourceTweet?e.sourceTweet?.content.text:e.tweet.content.text)??""}}var M=class e{client;listenersMap;endpoint;streamEndpoint;accessToken;initPromise=null;connectionGeneration=0;connectionRequested=false;static get isServer(){return typeof window>"u"}constructor({endpoint:t,streamEndpoint:n,accessToken:i}){this.endpoint=t,this.streamEndpoint=n,this.accessToken=i,this.listenersMap=new Map;}async initClient(t){if(this.client)return this.client;let n=await this.getTokenValue();if(t!==this.connectionGeneration)return;let i=this.buildWsUrl(this.streamEndpoint,n),r=new Centrifuge(i,{getToken:async()=>this.getTokenValue()});return r.on("connected",()=>{console.info("[media-track] connected");}).on("disconnected",s=>{console.warn("[media-track] disconnected",s);}).on("error",s=>{console.error("[media-track] error: ",s);}),this.client=r,r}async getTokenValue(){return typeof this.accessToken=="string"?this.accessToken:await this.accessToken.getToken()}buildWsUrl(t,n){let i=new URL(t);return i.searchParams.set("token",n),i.toString()}async ensureInitialized(){e.isServer||(this.connectionRequested||this.connect(),await this.initPromise);}async translate(t,n,i){let r=await this._requestOptions(),s=l(t,n,i);return (await httpPost(`${this.endpoint}/translation`,s,r)).data.target_text}connect(){if(e.isServer||this.connectionRequested)return;this.connectionRequested=true;let t=++this.connectionGeneration;this.initPromise=this.initClient(t).then(n=>{t===this.connectionGeneration&&n?.connect();});}disconnect(){this.connectionRequested=false,this.connectionGeneration+=1,this.client?.disconnect(),this.client=void 0,this.initPromise=null;}subscribe(t,n){let i=this.listenersMap.get(t);return i||(i=new Set,this.listenersMap.set(t,i)),i.add(n),this.ensureInitialized().then(()=>{let r=this.listenersMap.get(t),s=this.client;!r?.has(n)||!s||s.getSubscription(t)||(console.info("[media-track] create new sub: ",t),s.newSubscription(t,{delta:"fossil"}).on("subscribed",()=>{console.info("[media-track] subscribed",t);}).on("unsubscribed",()=>{console.info("[media-track] unsubscribed",t);}).on("publication",g=>{this.listenersMap.get(t)?.forEach(S=>S(g.data));}).subscribe());}),new a(this,t,n)}unsubscribe(t,n){let i=this.listenersMap.get(t);if(i&&(i.delete(n),console.info(`[media-track] unsubscribe ${t} listener, remain: ${i.size}`),i.size===0)){console.info(`[media-track] unsubscribe channel: ${t}`);let r=this.client?.getSubscription(t);r&&(r.unsubscribe(),this.client?.removeSubscription(r)),this.listenersMap.delete(t);}}subscribeTweetMedia({callback:t}){return this.subscribe("x-monitor-basic",n=>{try{t(o(n));}catch(i){console.error("[media-track] subscribeTweetMedia error: ",i);}})}subscribeTweetMediaToken({callback:t}){return this.subscribe("x-monitor-token",n=>{try{t(o(n));}catch(i){console.error("[media-track] subscribeTweetMediaToken error: ",i);}})}async generateMeme(t){let n=await this._requestOptions(),i=w(t),r=await httpPost(`${this.endpoint}/meme/generate`,i,n);return T(r.data)}async _requestOptions(){return {headers:{Authorization:`Bearer ${await this.getTokenValue()}`}}}},a=class{constructor(t,n,i){this.client=t;this.channel=n;this.fn=i;}unsubscribe(){this.client.unsubscribe(this.channel,this.fn);}};export{M as MediaTrackClient,T as convertFromGenerateMemeResult,q as convertFromSubscribedMediaToken,y as convertFromSubscribedSourceTweet,C as convertFromSubscribedTweet,p as convertFromSubscribedTweetContent,x as convertFromSubscribedTweetContentMedia,o as convertFromSubscribedTweetMedia,b as convertFromSubscribedTweetUser,w as toGenerateMemeParamsDTO,I as toGenerateTweetMemeParamsDTO,l as toTranslateParamsDTO,P as toTranslateTweetParamsDTO};//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/utils.ts","../../src/client/client.ts"],"names":["convertFromSubscribedTweetMedia","from","tryConvertFromSubscribedMediaToken","convertFromSubscribedTweet","convertFromSubscribedSourceTweet","resolveSubscribedMediaTokenChain","slug","Chain","chainIdBySlug","chain","createMediaToken","convertFromSubscribedMediaToken","priceChange","SafeBigNumber","convertFromSubscribedTweetUser","convertFromSubscribedTweetContent","convertFromSubscribedTweetContentMedia","convertFromGenerateMemeResult","toTranslateParamsDTO","media","targetLanguage","options","toTranslateTweetParamsDTO","toGenerateMemeParamsDTO","toGenerateTweetMemeParamsDTO","MediaTrackClient","_MediaTrackClient","endpoint","streamEndpoint","accessToken","token","wsUrl","Centrifuge","err","url","requestOptions","params","httpPost","channel","fn","listeners","ctx","it","Subscription","sub","callback","data","error","res","client"],"mappings":"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","file":"index.mjs","sourcesContent":["import { LocaleCode } from \"@liberfi.io/i18n\";\nimport { Chain } from \"@liberfi.io/types\";\nimport { chainIdBySlug, SafeBigNumber } from \"@liberfi.io/utils\";\nimport {\n GeneratedMemeInfo,\n IMedia,\n MediaToken,\n SourceTweet,\n Tweet,\n TweetContent,\n TweetContentMedia,\n TweetMedia,\n TweetUser,\n} from \"../types\";\nimport {\n GenerateMemeResult,\n SubscribedMediaToken,\n SubscribedSourceTweet,\n SubscribedTweet,\n SubscribedTweetContent,\n SubscribedTweetContentMedia,\n SubscribedTweetMedia,\n SubscribedTweetUser,\n TranslateTweetRequest,\n} from \"./types\";\n\nexport function convertFromSubscribedTweetMedia(\n from: SubscribedTweetMedia,\n): TweetMedia {\n return {\n id: from.i,\n type: \"tweet\",\n tokenType: from.tt,\n // Token metadata is optional enrichment; an unknown chain must not drop the tweet.\n token: from.t ? tryConvertFromSubscribedMediaToken(from.t) : undefined,\n tweet: convertFromSubscribedTweet(from.tw),\n sourceTweet: from.s ? convertFromSubscribedSourceTweet(from.s) : undefined,\n };\n}\n\nfunction resolveSubscribedMediaTokenChain(slug: string): Chain | undefined {\n return slug === \"sol\" ? Chain.SOLANA : chainIdBySlug(slug);\n}\n\nfunction tryConvertFromSubscribedMediaToken(\n from: SubscribedMediaToken,\n): MediaToken | undefined {\n const chain = resolveSubscribedMediaTokenChain(from.c);\n return chain ? createMediaToken(from, chain) : undefined;\n}\n\nexport function convertFromSubscribedMediaToken(\n from: SubscribedMediaToken,\n): MediaToken {\n const chain = resolveSubscribedMediaTokenChain(from.c);\n if (!chain) {\n throw new Error(`Unsupported chain: ${from.c}`);\n }\n return createMediaToken(from, chain);\n}\n\nfunction createMediaToken(\n from: SubscribedMediaToken,\n chain: Chain,\n): MediaToken {\n const priceChange =\n from.p && from.p1 && new SafeBigNumber(from.p1).isPositive()\n ? new SafeBigNumber(from.p)\n .minus(from.p1)\n .div(from.p1)\n .times(100)\n .toString()\n : undefined;\n return {\n chain,\n address: from.a,\n symbol: from.s,\n image: from.i,\n latestPrice: from.p,\n previousPrice: from.p1,\n priceChange,\n };\n}\n\nexport function convertFromSubscribedTweet(from: SubscribedTweet): Tweet {\n return {\n tweetId: from.i,\n type: from.t,\n timestamp: Number(from.ts),\n user: convertFromSubscribedTweetUser(from.u),\n content: convertFromSubscribedTweetContent(from.c),\n };\n}\n\nexport function convertFromSubscribedSourceTweet(\n from: SubscribedSourceTweet,\n): SourceTweet {\n return {\n tweetId: from.i,\n user: convertFromSubscribedTweetUser(from.u),\n content: convertFromSubscribedTweetContent(from.c),\n };\n}\n\nexport function convertFromSubscribedTweetUser(\n from: SubscribedTweetUser,\n): TweetUser {\n return {\n username: from.s,\n screenName: from.n,\n avatar: from.a,\n tags: from.ut,\n };\n}\n\nexport function convertFromSubscribedTweetContent(\n from: SubscribedTweetContent,\n): TweetContent {\n return {\n text: from.t,\n medias: from.m\n ? from.m.map(convertFromSubscribedTweetContentMedia).filter(Boolean)\n : undefined,\n };\n}\n\nexport function convertFromSubscribedTweetContentMedia(\n from: SubscribedTweetContentMedia,\n): TweetContentMedia {\n return {\n type: from.t,\n url: from.u,\n };\n}\n\nexport function convertFromGenerateMemeResult(\n from: GenerateMemeResult,\n): GeneratedMemeInfo {\n return {\n symbol: from.ticker,\n name: from.coin_name,\n image: from.icon_url,\n };\n}\n\nexport function toTranslateParamsDTO(\n media: IMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n): TranslateTweetRequest {\n switch (media.type) {\n case \"tweet\":\n return toTranslateTweetParamsDTO(\n media as TweetMedia,\n targetLanguage,\n options,\n );\n default:\n throw new Error(`Unsupported media type: ${media.type}`);\n }\n}\n\nexport function toGenerateMemeParamsDTO(media: IMedia) {\n switch (media.type) {\n case \"tweet\":\n return toGenerateTweetMemeParamsDTO(media as TweetMedia);\n default:\n throw new Error(`Unsupported media type: ${media.type}`);\n }\n}\n\nexport function toGenerateTweetMemeParamsDTO(media: TweetMedia) {\n return {\n tweet_id: media.tweet.tweetId,\n tweet_info: media.tweet.content.text,\n };\n}\n\nexport function toTranslateTweetParamsDTO(\n media: TweetMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n): TranslateTweetRequest {\n return {\n res_type: \"tw\",\n res_id: options?.sourceTweet\n ? (media.sourceTweet?.tweetId ?? media.id)\n : media.id,\n source_lang: options?.sourceLanguage,\n target_lang: targetLanguage,\n text:\n (options?.sourceTweet\n ? media.sourceTweet?.content.text\n : media.tweet.content.text) ?? \"\",\n };\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable no-console */\nimport { Centrifuge } from \"@chainstream-io/centrifuge\";\nimport { LocaleCode } from \"@liberfi.io/i18n\";\nimport { ISubscription } from \"@liberfi.io/types\";\nimport { httpPost } from \"@liberfi.io/utils\";\nimport {\n GeneratedMemeInfo,\n IMedia,\n IMediaTrackClient,\n SubscribeTweetMediasOptions,\n} from \"../types\";\nimport {\n GenerateMemeResponse,\n SubscribedTweetMedia,\n TranslateTweetResponse,\n} from \"./types\";\nimport {\n convertFromGenerateMemeResult,\n convertFromSubscribedTweetMedia,\n toGenerateMemeParamsDTO,\n toTranslateParamsDTO,\n} from \"./utils\";\n\nexport interface MediaTrackClientOptions {\n endpoint: string;\n streamEndpoint: string;\n accessToken:\n | string\n | {\n getToken(): Promise<string> | string;\n };\n}\n\nexport class MediaTrackClient implements IMediaTrackClient {\n private client!: Centrifuge;\n private listenersMap: Map<string, Set<(data: any) => void>>;\n private endpoint: string;\n private streamEndpoint: string;\n private accessToken: MediaTrackClientOptions[\"accessToken\"];\n private initPromise: Promise<void> | null = null;\n\n private static get isServer(): boolean {\n return typeof window === \"undefined\";\n }\n\n constructor({\n endpoint,\n streamEndpoint,\n accessToken,\n }: MediaTrackClientOptions) {\n this.endpoint = endpoint;\n this.streamEndpoint = streamEndpoint;\n this.accessToken = accessToken;\n this.listenersMap = new Map();\n\n if (!MediaTrackClient.isServer) {\n this.connect();\n }\n }\n\n private async initClient() {\n if (this.client) {\n return;\n }\n const token = await this.getTokenValue();\n const wsUrl = this.buildWsUrl(this.streamEndpoint, token);\n this.client = new Centrifuge(wsUrl, {\n getToken: async () => {\n return this.getTokenValue();\n },\n });\n\n this.client\n .on(\"connected\", () => {\n console.info(\"[media-track] connected\");\n })\n .on(\"disconnected\", (err) => {\n console.warn(\"[media-track] disconnected\", err);\n })\n .on(\"error\", (err) => {\n console.error(\"[media-track] error: \", err);\n });\n }\n\n private async getTokenValue(): Promise<string> {\n return typeof this.accessToken === \"string\"\n ? this.accessToken\n : await this.accessToken.getToken();\n }\n\n private buildWsUrl(endpoint: string, token: string): string {\n const url = new URL(endpoint);\n url.searchParams.set(\"token\", token);\n return url.toString();\n }\n\n private async ensureInitialized() {\n if (MediaTrackClient.isServer) return;\n if (!this.initPromise) {\n this.connect();\n }\n await this.initPromise;\n }\n\n async translate(\n media: IMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n ): Promise<string> {\n const requestOptions = await this._requestOptions();\n const params = toTranslateParamsDTO(media, targetLanguage, options);\n const res = await httpPost<TranslateTweetResponse>(\n `${this.endpoint}/translation`,\n params,\n requestOptions,\n );\n return res.data.target_text;\n }\n\n /**\n * Connect to the media track realtime server.\n * Lazily initializes the Centrifuge client on first call.\n * No-op when called during SSR (Node.js).\n */\n connect() {\n if (MediaTrackClient.isServer) return;\n this.initPromise = this.initClient().then(() => {\n this.client.connect();\n });\n }\n\n /**\n * Disconnect and release the underlying Centrifuge transport.\n */\n disconnect() {\n if (this.client) {\n this.client.disconnect();\n }\n this.initPromise = null;\n }\n\n subscribe<T = any>(channel: string, fn: (data: T) => void): ISubscription {\n let listeners = this.listenersMap.get(channel);\n if (!listeners) {\n listeners = new Set();\n this.listenersMap.set(channel, listeners);\n }\n listeners.add(fn);\n\n void this.ensureInitialized().then(() => {\n if (!this.client.getSubscription(channel)) {\n console.info(\"[media-track] create new sub: \", channel);\n\n const sub = this.client.newSubscription(channel, {\n delta: \"fossil\",\n });\n\n sub\n .on(\"subscribed\", () => {\n console.info(\"[media-track] subscribed\", channel);\n })\n .on(\"unsubscribed\", () => {\n console.info(\"[media-track] unsubscribed\", channel);\n })\n .on(\"publication\", (ctx) => {\n const ls = this.listenersMap.get(channel);\n ls?.forEach((it) => it(ctx.data));\n })\n .subscribe();\n }\n });\n\n return new Subscription<T>(this, channel, fn);\n }\n\n unsubscribe<T = any>(channel: string, fn: (data: T) => void) {\n const listeners = this.listenersMap.get(channel);\n if (!listeners) return;\n\n listeners.delete(fn);\n console.info(\n `[media-track] unsubscribe ${channel} listener, remain: ${listeners.size}`,\n );\n\n if (listeners.size === 0) {\n console.info(`[media-track] unsubscribe channel: ${channel}`);\n\n const sub = this.client.getSubscription(channel);\n if (sub) {\n sub.unsubscribe();\n this.client.removeSubscription(sub);\n }\n\n this.listenersMap.delete(channel);\n }\n }\n\n subscribeTweetMedia({\n callback,\n }: SubscribeTweetMediasOptions): ISubscription {\n return this.subscribe(\"x-monitor-basic\", (data: SubscribedTweetMedia) => {\n try {\n callback(convertFromSubscribedTweetMedia(data));\n } catch (error) {\n console.error(\"[media-track] subscribeTweetMedia error: \", error);\n }\n });\n }\n\n subscribeTweetMediaToken({\n callback,\n }: SubscribeTweetMediasOptions): ISubscription {\n return this.subscribe(\"x-monitor-token\", (data: SubscribedTweetMedia) => {\n try {\n callback(convertFromSubscribedTweetMedia(data));\n } catch (error) {\n console.error(\"[media-track] subscribeTweetMediaToken error: \", error);\n }\n });\n }\n\n async generateMeme(media: IMedia): Promise<GeneratedMemeInfo> {\n const requestOptions = await this._requestOptions();\n const params = toGenerateMemeParamsDTO(media);\n const res = await httpPost<GenerateMemeResponse>(\n `${this.endpoint}/meme/generate`,\n params,\n requestOptions,\n );\n return convertFromGenerateMemeResult(res.data);\n }\n\n async _requestOptions(): Promise<Omit<RequestInit, \"method\">> {\n const token = await this.getTokenValue();\n return {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n };\n }\n}\n\nclass Subscription<T> {\n constructor(\n private readonly client: MediaTrackClient,\n private readonly channel: string,\n private readonly fn: (data: T) => void,\n ) {}\n\n unsubscribe() {\n this.client.unsubscribe(this.channel, this.fn);\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/client/utils.ts","../../src/client/client.ts"],"names":["convertFromSubscribedTweetMedia","from","tryConvertFromSubscribedMediaToken","convertFromSubscribedTweet","convertFromSubscribedSourceTweet","resolveSubscribedMediaTokenChain","slug","Chain","chainIdBySlug","chain","createMediaToken","convertFromSubscribedMediaToken","priceChange","SafeBigNumber","convertFromSubscribedTweetUser","convertFromSubscribedTweetContent","convertFromSubscribedTweetContentMedia","convertFromGenerateMemeResult","toTranslateParamsDTO","media","targetLanguage","options","toTranslateTweetParamsDTO","toGenerateMemeParamsDTO","toGenerateTweetMemeParamsDTO","MediaTrackClient","_MediaTrackClient","endpoint","streamEndpoint","accessToken","generation","token","wsUrl","client","Centrifuge","err","url","requestOptions","params","httpPost","channel","fn","listeners","activeListeners","ctx","it","Subscription","sub","callback","data","error","res"],"mappings":"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","file":"index.mjs","sourcesContent":["import { LocaleCode } from \"@liberfi.io/i18n\";\nimport { Chain } from \"@liberfi.io/types\";\nimport { chainIdBySlug, SafeBigNumber } from \"@liberfi.io/utils\";\nimport {\n GeneratedMemeInfo,\n IMedia,\n MediaToken,\n SourceTweet,\n Tweet,\n TweetContent,\n TweetContentMedia,\n TweetMedia,\n TweetUser,\n} from \"../types\";\nimport {\n GenerateMemeResult,\n SubscribedMediaToken,\n SubscribedSourceTweet,\n SubscribedTweet,\n SubscribedTweetContent,\n SubscribedTweetContentMedia,\n SubscribedTweetMedia,\n SubscribedTweetUser,\n TranslateTweetRequest,\n} from \"./types\";\n\nexport function convertFromSubscribedTweetMedia(\n from: SubscribedTweetMedia,\n): TweetMedia {\n return {\n id: from.i,\n type: \"tweet\",\n tokenType: from.tt,\n // Token metadata is optional enrichment; an unknown chain must not drop the tweet.\n token: from.t ? tryConvertFromSubscribedMediaToken(from.t) : undefined,\n tweet: convertFromSubscribedTweet(from.tw),\n sourceTweet: from.s ? convertFromSubscribedSourceTweet(from.s) : undefined,\n };\n}\n\nfunction resolveSubscribedMediaTokenChain(slug: string): Chain | undefined {\n return slug === \"sol\" ? Chain.SOLANA : chainIdBySlug(slug);\n}\n\nfunction tryConvertFromSubscribedMediaToken(\n from: SubscribedMediaToken,\n): MediaToken | undefined {\n const chain = resolveSubscribedMediaTokenChain(from.c);\n return chain ? createMediaToken(from, chain) : undefined;\n}\n\nexport function convertFromSubscribedMediaToken(\n from: SubscribedMediaToken,\n): MediaToken {\n const chain = resolveSubscribedMediaTokenChain(from.c);\n if (!chain) {\n throw new Error(`Unsupported chain: ${from.c}`);\n }\n return createMediaToken(from, chain);\n}\n\nfunction createMediaToken(\n from: SubscribedMediaToken,\n chain: Chain,\n): MediaToken {\n const priceChange =\n from.p && from.p1 && new SafeBigNumber(from.p1).isPositive()\n ? new SafeBigNumber(from.p)\n .minus(from.p1)\n .div(from.p1)\n .times(100)\n .toString()\n : undefined;\n return {\n chain,\n address: from.a,\n symbol: from.s,\n image: from.i,\n latestPrice: from.p,\n previousPrice: from.p1,\n priceChange,\n };\n}\n\nexport function convertFromSubscribedTweet(from: SubscribedTweet): Tweet {\n return {\n tweetId: from.i,\n type: from.t,\n timestamp: Number(from.ts),\n user: convertFromSubscribedTweetUser(from.u),\n content: convertFromSubscribedTweetContent(from.c),\n };\n}\n\nexport function convertFromSubscribedSourceTweet(\n from: SubscribedSourceTweet,\n): SourceTweet {\n return {\n tweetId: from.i,\n user: convertFromSubscribedTweetUser(from.u),\n content: convertFromSubscribedTweetContent(from.c),\n };\n}\n\nexport function convertFromSubscribedTweetUser(\n from: SubscribedTweetUser,\n): TweetUser {\n return {\n username: from.s,\n screenName: from.n,\n avatar: from.a,\n tags: from.ut,\n };\n}\n\nexport function convertFromSubscribedTweetContent(\n from: SubscribedTweetContent,\n): TweetContent {\n return {\n text: from.t,\n medias: from.m\n ? from.m.map(convertFromSubscribedTweetContentMedia).filter(Boolean)\n : undefined,\n };\n}\n\nexport function convertFromSubscribedTweetContentMedia(\n from: SubscribedTweetContentMedia,\n): TweetContentMedia {\n return {\n type: from.t,\n url: from.u,\n };\n}\n\nexport function convertFromGenerateMemeResult(\n from: GenerateMemeResult,\n): GeneratedMemeInfo {\n return {\n symbol: from.ticker,\n name: from.coin_name,\n image: from.icon_url,\n };\n}\n\nexport function toTranslateParamsDTO(\n media: IMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n): TranslateTweetRequest {\n switch (media.type) {\n case \"tweet\":\n return toTranslateTweetParamsDTO(\n media as TweetMedia,\n targetLanguage,\n options,\n );\n default:\n throw new Error(`Unsupported media type: ${media.type}`);\n }\n}\n\nexport function toGenerateMemeParamsDTO(media: IMedia) {\n switch (media.type) {\n case \"tweet\":\n return toGenerateTweetMemeParamsDTO(media as TweetMedia);\n default:\n throw new Error(`Unsupported media type: ${media.type}`);\n }\n}\n\nexport function toGenerateTweetMemeParamsDTO(media: TweetMedia) {\n return {\n tweet_id: media.tweet.tweetId,\n tweet_info: media.tweet.content.text,\n };\n}\n\nexport function toTranslateTweetParamsDTO(\n media: TweetMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n): TranslateTweetRequest {\n return {\n res_type: \"tw\",\n res_id: options?.sourceTweet\n ? (media.sourceTweet?.tweetId ?? media.id)\n : media.id,\n source_lang: options?.sourceLanguage,\n target_lang: targetLanguage,\n text:\n (options?.sourceTweet\n ? media.sourceTweet?.content.text\n : media.tweet.content.text) ?? \"\",\n };\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable no-console */\nimport { Centrifuge } from \"@chainstream-io/centrifuge\";\nimport { LocaleCode } from \"@liberfi.io/i18n\";\nimport { ISubscription } from \"@liberfi.io/types\";\nimport { httpPost } from \"@liberfi.io/utils\";\nimport {\n GeneratedMemeInfo,\n IMedia,\n IMediaTrackClient,\n SubscribeTweetMediasOptions,\n} from \"../types\";\nimport {\n GenerateMemeResponse,\n SubscribedTweetMedia,\n TranslateTweetResponse,\n} from \"./types\";\nimport {\n convertFromGenerateMemeResult,\n convertFromSubscribedTweetMedia,\n toGenerateMemeParamsDTO,\n toTranslateParamsDTO,\n} from \"./utils\";\n\nexport interface MediaTrackClientOptions {\n endpoint: string;\n streamEndpoint: string;\n accessToken:\n | string\n | {\n getToken(): Promise<string> | string;\n };\n}\n\nexport class MediaTrackClient implements IMediaTrackClient {\n private client: Centrifuge | undefined;\n private listenersMap: Map<string, Set<(data: any) => void>>;\n private endpoint: string;\n private streamEndpoint: string;\n private accessToken: MediaTrackClientOptions[\"accessToken\"];\n private initPromise: Promise<void> | null = null;\n private connectionGeneration = 0;\n private connectionRequested = false;\n\n private static get isServer(): boolean {\n return typeof window === \"undefined\";\n }\n\n constructor({\n endpoint,\n streamEndpoint,\n accessToken,\n }: MediaTrackClientOptions) {\n this.endpoint = endpoint;\n this.streamEndpoint = streamEndpoint;\n this.accessToken = accessToken;\n this.listenersMap = new Map();\n }\n\n private async initClient(\n generation: number,\n ): Promise<Centrifuge | undefined> {\n if (this.client) {\n return this.client;\n }\n const token = await this.getTokenValue();\n if (generation !== this.connectionGeneration) {\n return undefined;\n }\n const wsUrl = this.buildWsUrl(this.streamEndpoint, token);\n const client = new Centrifuge(wsUrl, {\n getToken: async () => {\n return this.getTokenValue();\n },\n });\n\n client\n .on(\"connected\", () => {\n console.info(\"[media-track] connected\");\n })\n .on(\"disconnected\", (err) => {\n console.warn(\"[media-track] disconnected\", err);\n })\n .on(\"error\", (err) => {\n console.error(\"[media-track] error: \", err);\n });\n this.client = client;\n return client;\n }\n\n private async getTokenValue(): Promise<string> {\n return typeof this.accessToken === \"string\"\n ? this.accessToken\n : await this.accessToken.getToken();\n }\n\n private buildWsUrl(endpoint: string, token: string): string {\n const url = new URL(endpoint);\n url.searchParams.set(\"token\", token);\n return url.toString();\n }\n\n private async ensureInitialized() {\n if (MediaTrackClient.isServer) return;\n if (!this.connectionRequested) {\n this.connect();\n }\n await this.initPromise;\n }\n\n async translate(\n media: IMedia,\n targetLanguage: LocaleCode,\n options?: { sourceLanguage?: LocaleCode; sourceTweet?: boolean },\n ): Promise<string> {\n const requestOptions = await this._requestOptions();\n const params = toTranslateParamsDTO(media, targetLanguage, options);\n const res = await httpPost<TranslateTweetResponse>(\n `${this.endpoint}/translation`,\n params,\n requestOptions,\n );\n return res.data.target_text;\n }\n\n /**\n * Connect to the media track realtime server.\n * Lazily initializes the Centrifuge client on first call.\n * No-op when called during SSR (Node.js).\n */\n connect() {\n if (MediaTrackClient.isServer || this.connectionRequested) return;\n this.connectionRequested = true;\n const generation = ++this.connectionGeneration;\n this.initPromise = this.initClient(generation).then((client) => {\n if (generation === this.connectionGeneration) {\n client?.connect();\n }\n });\n }\n\n /**\n * Disconnect and release the underlying Centrifuge transport.\n */\n disconnect() {\n this.connectionRequested = false;\n this.connectionGeneration += 1;\n this.client?.disconnect();\n this.client = undefined;\n this.initPromise = null;\n }\n\n subscribe<T = any>(channel: string, fn: (data: T) => void): ISubscription {\n let listeners = this.listenersMap.get(channel);\n if (!listeners) {\n listeners = new Set();\n this.listenersMap.set(channel, listeners);\n }\n listeners.add(fn);\n\n void this.ensureInitialized().then(() => {\n const activeListeners = this.listenersMap.get(channel);\n const client = this.client;\n if (!activeListeners?.has(fn) || !client) return;\n\n if (!client.getSubscription(channel)) {\n console.info(\"[media-track] create new sub: \", channel);\n\n const sub = client.newSubscription(channel, {\n delta: \"fossil\",\n });\n\n sub\n .on(\"subscribed\", () => {\n console.info(\"[media-track] subscribed\", channel);\n })\n .on(\"unsubscribed\", () => {\n console.info(\"[media-track] unsubscribed\", channel);\n })\n .on(\"publication\", (ctx) => {\n const ls = this.listenersMap.get(channel);\n ls?.forEach((it) => it(ctx.data));\n })\n .subscribe();\n }\n });\n\n return new Subscription<T>(this, channel, fn);\n }\n\n unsubscribe<T = any>(channel: string, fn: (data: T) => void) {\n const listeners = this.listenersMap.get(channel);\n if (!listeners) return;\n\n listeners.delete(fn);\n console.info(\n `[media-track] unsubscribe ${channel} listener, remain: ${listeners.size}`,\n );\n\n if (listeners.size === 0) {\n console.info(`[media-track] unsubscribe channel: ${channel}`);\n\n const sub = this.client?.getSubscription(channel);\n if (sub) {\n sub.unsubscribe();\n this.client?.removeSubscription(sub);\n }\n\n this.listenersMap.delete(channel);\n }\n }\n\n subscribeTweetMedia({\n callback,\n }: SubscribeTweetMediasOptions): ISubscription {\n return this.subscribe(\"x-monitor-basic\", (data: SubscribedTweetMedia) => {\n try {\n callback(convertFromSubscribedTweetMedia(data));\n } catch (error) {\n console.error(\"[media-track] subscribeTweetMedia error: \", error);\n }\n });\n }\n\n subscribeTweetMediaToken({\n callback,\n }: SubscribeTweetMediasOptions): ISubscription {\n return this.subscribe(\"x-monitor-token\", (data: SubscribedTweetMedia) => {\n try {\n callback(convertFromSubscribedTweetMedia(data));\n } catch (error) {\n console.error(\"[media-track] subscribeTweetMediaToken error: \", error);\n }\n });\n }\n\n async generateMeme(media: IMedia): Promise<GeneratedMemeInfo> {\n const requestOptions = await this._requestOptions();\n const params = toGenerateMemeParamsDTO(media);\n const res = await httpPost<GenerateMemeResponse>(\n `${this.endpoint}/meme/generate`,\n params,\n requestOptions,\n );\n return convertFromGenerateMemeResult(res.data);\n }\n\n async _requestOptions(): Promise<Omit<RequestInit, \"method\">> {\n const token = await this.getTokenValue();\n return {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n };\n }\n}\n\nclass Subscription<T> {\n constructor(\n private readonly client: MediaTrackClient,\n private readonly channel: string,\n private readonly fn: (data: T) => void,\n ) {}\n\n unsubscribe() {\n this.client.unsubscribe(this.channel, this.fn);\n }\n}\n"]}
package/dist/index.d.mts CHANGED
@@ -170,7 +170,8 @@ declare function useTranslateTweetMediaMutation(options?: Omit<UseMutationOption
170
170
 
171
171
  type MediaTrackProviderProps = PropsWithChildren<{
172
172
  client: IMediaTrackClient;
173
+ active?: boolean;
173
174
  }>;
174
- declare function MediaTrackProvider({ client, children, }: MediaTrackProviderProps): react_jsx_runtime.JSX.Element;
175
+ declare function MediaTrackProvider({ client, children, active, }: MediaTrackProviderProps): react_jsx_runtime.JSX.Element;
175
176
 
176
177
  export { GeneratedMemeInfo, IMediaTrackClient, MediaImage, MediaTrackContext, type MediaTrackContextValue, MediaTrackProvider, type MediaTrackProviderProps, type MediaTrackRuntime, MediaTrackRuntimeContext, MediaVideo, Medias, TextExpand, Translate, TweetContentMedia, TweetItem, TweetMedia, TweetOriginal, TweetQuote, TweetReply, TweetRetweet, TweetSkeleton, TweetSkeletonList, TweetSource, TweetUser, Tweets, TweetsWidget, type TweetsWidgetProps, type UseTranslateTweetMediaParams, UserAvatar, UserInfo, createMediaTrackRuntime, translateTweetMedia, useGenerateTweetMediaMemeMutation, useMediaTrackClient, useMediaTrackContext, useMediaTrackRuntime, useTranslateTweetMediaMutation, useTweets };
package/dist/index.d.ts CHANGED
@@ -170,7 +170,8 @@ declare function useTranslateTweetMediaMutation(options?: Omit<UseMutationOption
170
170
 
171
171
  type MediaTrackProviderProps = PropsWithChildren<{
172
172
  client: IMediaTrackClient;
173
+ active?: boolean;
173
174
  }>;
174
- declare function MediaTrackProvider({ client, children, }: MediaTrackProviderProps): react_jsx_runtime.JSX.Element;
175
+ declare function MediaTrackProvider({ client, children, active, }: MediaTrackProviderProps): react_jsx_runtime.JSX.Element;
175
176
 
176
177
  export { GeneratedMemeInfo, IMediaTrackClient, MediaImage, MediaTrackContext, type MediaTrackContextValue, MediaTrackProvider, type MediaTrackProviderProps, type MediaTrackRuntime, MediaTrackRuntimeContext, MediaVideo, Medias, TextExpand, Translate, TweetContentMedia, TweetItem, TweetMedia, TweetOriginal, TweetQuote, TweetReply, TweetRetweet, TweetSkeleton, TweetSkeletonList, TweetSource, TweetUser, Tweets, TweetsWidget, type TweetsWidgetProps, type UseTranslateTweetMediaParams, UserAvatar, UserInfo, createMediaTrackRuntime, translateTweetMedia, useGenerateTweetMediaMemeMutation, useMediaTrackClient, useMediaTrackContext, useMediaTrackRuntime, useTranslateTweetMediaMutation, useTweets };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var hooks=require('@liberfi.io/hooks'),ui=require('@liberfi.io/ui'),jsxRuntime=require('react/jsx-runtime'),utils=require('@liberfi.io/utils'),react=require('react'),i18n=require('@liberfi.io/i18n'),reactQuery=require('@tanstack/react-query');function S({src:e}){let[t,{setTrue:o}]=hooks.useBoolean(false);return e?jsxRuntime.jsx(ui.Skeleton,{isLoaded:t,className:"w-full h-auto",children:jsxRuntime.jsx("img",{src:e,className:"w-full h-full object-cover aspect-video",onLoad:()=>{o();}})}):null}function L({src:e}){return e?jsxRuntime.jsx("div",{className:"w-full h-full overflow-hidden rounded-md mt-2",children:jsxRuntime.jsx("iframe",{className:"w-full h-full aspect-video",src:e,allowFullScreen:true})}):null}function E({medias:e,tweetHref:t}){let o=e.filter(a=>a.type==="image"),n=e.filter(a=>a.type==="video"),r=()=>n.length?jsxRuntime.jsx("div",{className:"grid grid-cols-1 gap-[1px] overflow-hidden rounded-md",children:n.map(a=>jsxRuntime.jsx(L,{src:a.url},a.url))}):null,i=()=>o.length?jsxRuntime.jsx("div",{className:"grid grid-cols-1 gap-[1px] overflow-hidden rounded-md",children:o.map(a=>jsxRuntime.jsx(ui.Link,{href:t,target:"_blank",children:jsxRuntime.jsx(S,{src:a.url})},a.url))}):null;return jsxRuntime.jsxs("div",{className:"flex flex-col gap-2",children:[r(),i()]})}function U({url:e,name:t="",size:o=36}){let n=react.useMemo(()=>t?t.slice(0,2):"N/A",[t]);return jsxRuntime.jsx(ui.Skeleton,{className:"flex rounded-full flex-shrink-0",style:{width:o,height:o},isLoaded:!!e,children:jsxRuntime.jsx(ui.Avatar,{size:"md",color:"primary",radius:"full",showFallback:true,name:n,src:e,style:{width:o,height:o}})})}function B({user:e,renderTimestamp:t,renderActions:o}){return jsxRuntime.jsxs("div",{className:"flex items-center justify-between gap-1",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-1",children:[jsxRuntime.jsx(U,{url:e.avatar,name:e.username}),jsxRuntime.jsxs("div",{className:"flex flex-col gap-0.5",children:[jsxRuntime.jsxs("div",{className:"flex flex-row items-baseline gap-1",children:[jsxRuntime.jsx("span",{className:"text-foreground font-semibold truncate leading-none",children:e.username}),t]}),jsxRuntime.jsxs(ui.Link,{target:"_blank",underline:"hover",className:"text-text-muted text-sm leading-none",href:utils.twitterUserUrl(e.screenName??e.username),children:["@",e.screenName??e.username]})]})]}),o]})}var N=react.createContext({});var h=react.createContext(null);function O(){let e=react.useContext(N);if(!e)throw new Error("useMediaTrackContext must be used within a MediaTrackProvider");return e}function y(){let{client:e}=O();return e}function Ue(e={}){let t=y();return reactQuery.useMutation({mutationFn:async o=>t.generateMeme(o),...e})}function F(){let e=react.useContext(h);if(!e)throw new Error("useMediaTrackRuntime must be used within a MediaTrackProvider");return e}async function se(e,{media:t,targetLanguage:o,options:n}){return await e.translate(t,o,n)}function H(e={}){let t=y();return reactQuery.useMutation({mutationFn:async o=>se(t,o),...e})}function R(e){let t=/(https?:\/\/[^\s]+|www\.[^\s]+)/gi,o=/#[\w]+/g,n=/\$[A-Za-z][A-Za-z0-9_]*/g,r=[],i;for(;(i=t.exec(e))!==null;)r.push({index:i.index,length:i[0].length,text:i[0],type:"url"});for(;(i=o.exec(e))!==null;){let s=i.index;r.some(m=>s>=m.index&&s<m.index+m.length)||r.push({index:s,length:i[0].length,text:i[0],type:"hashtag"});}for(;(i=n.exec(e))!==null;){let s=i.index;r.some(m=>s>=m.index&&s<m.index+m.length)||r.push({index:s,length:i[0].length,text:i[0],type:"symbol"});}r.sort((s,c)=>s.index-c.index);let a=[],l=0,d=0;return r.forEach(s=>{if(s.index>l&&a.push(e.slice(l,s.index)),s.type==="url"){let c=s.text.startsWith("http")?s.text:`https://${s.text}`;a.push(jsxRuntime.jsx("a",{href:c,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",onClick:m=>m.stopPropagation(),children:s.text},d++));}else if(s.type==="hashtag"){let m=`https://x.com/hashtag/${s.text.slice(1)}`;a.push(jsxRuntime.jsx("a",{href:m,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",onClick:T=>T.stopPropagation(),children:s.text},d++));}else s.type==="symbol"&&a.push(jsxRuntime.jsx("span",{className:"text-primary",children:s.text},d++));l=s.index+s.length;}),l<e.length&&a.push(e.slice(l)),a.length>0?a:[e]}function W({data:e,embed:t,renderActions:o}){let[n,{toggle:r}]=hooks.useBoolean(false),{t:i,i18n:a}=i18n.useTranslation(),{mutateAsync:l,isPending:d}=H(),[s,c]=react.useState(null),m=react.useCallback(async T=>{if(T.stopPropagation(),r(),!s){let I=await l({media:e,targetLanguage:a.language,options:{sourceTweet:t}}),Me=R(I);c(Me);}},[r,l,e,a.language,s,t]);return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-1 text-xs",children:[jsxRuntime.jsxs("div",{onClick:m,className:"flex items-center gap-0.5 cursor-pointer text-primary hover:text-foreground",children:[jsxRuntime.jsx(ui.TranslateIcon,{width:"14",height:"14"}),i(n?"mediaTrack.tweets.translate.hide":"mediaTrack.tweets.translate.show")]}),o]}),jsxRuntime.jsx("div",{className:ui.cn(!n&&"hidden"),onClick:T=>{T.stopPropagation();},children:n&&jsxRuntime.jsxs("div",{className:"bg-content2 rounded-md p-2 text-text-primary text-sm leading-5",children:[s,d&&jsxRuntime.jsx(ui.Skeleton,{className:"w-full h-4 rounded-md"})]})})]})}function G({isExpanded:e,onToggleExpand:t}){let{t:o}=i18n.useTranslation(),n=()=>e?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(ui.ChevronUpIcon,{className:"border border-current",width:"12",height:"12"}),"\xA0",o("mediaTrack.tweets.collapse")]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(ui.ChevronDownIcon,{className:"border border-current",width:"12",height:"12"}),"\xA0",o("mediaTrack.tweets.expand")]});return e===void 0?null:jsxRuntime.jsxs("div",{className:"flex items-center gap-1",children:[jsxRuntime.jsx("div",{className:"w-px h-2.5 bg-line-300"}),jsxRuntime.jsx("button",{onClick:r=>{r.stopPropagation(),t?.(!e);},className:"flex items-center text-text-muted hover:text-foreground text-xs",children:n()})]})}function de({content:e,isExpanded:t=false,onLoad:o}){let n=react.useRef(null),r=react.useMemo(()=>R(e),[e]);return react.useEffect(()=>{let i=n.current;!o||!i||i.scrollHeight>i.clientHeight&&o?.();},[t,o]),jsxRuntime.jsx("div",{ref:n,className:["text-text-primary text-sm leading-5",t?"":"line-clamp-3"].join(" "),onClick:i=>{i.stopPropagation();},children:r})}function u({data:e,headerActions:t,footerActions:o,embed:n=false,indicator:r,children:i}){let{formatAge:a}=i18n.useLocalizedTimeFormatter(),[l,d]=react.useState(void 0),s=react.useMemo(()=>n?"bg-default-50 rounded-lg p-3 w-full mx-auto":"bg-default-100 hover:bg-default-200 rounded-lg p-3 w-full mx-auto",[n]),c=react.useMemo(()=>n?e.sourceTweet:e.tweet,[e,n]),m=hooks.useTickAge(c.timestamp);return jsxRuntime.jsxs("div",{className:ui.cn("flex flex-col gap-1.5 cursor-pointer",s),onClick:()=>{window.open(utils.twitterTweetUrl(c.tweetId),"_blank");},children:[jsxRuntime.jsx(B,{user:c.user,renderTimestamp:n?void 0:jsxRuntime.jsx("div",{className:"text-xs text-primary",children:a(m)}),renderActions:t}),r,c.content.text&&jsxRuntime.jsx(de,{content:c.content.text,isExpanded:l,onLoad:()=>d(false)}),c.content.text&&jsxRuntime.jsx(W,{data:e,embed:n,text:c.content.text,renderActions:jsxRuntime.jsx(G,{isExpanded:l,onToggleExpand:d})}),jsxRuntime.jsx("div",{className:ui.cn((!c.content.medias||c.content.medias.length===0)&&"hidden"),children:c.content.medias&&c.content.medias.length>0&&jsxRuntime.jsx(E,{medias:c.content.medias,tweetHref:utils.twitterTweetUrl(c.tweetId)})}),i,o]})}function D({data:e,headerActions:t,footerActions:o}){return jsxRuntime.jsx(u,{data:e,headerActions:t,footerActions:o})}function Q({data:e,headerActions:t,footerActions:o}){let r=!!e.sourceTweet;return jsxRuntime.jsx(u,{data:e,headerActions:t,footerActions:o,children:r?jsxRuntime.jsx(u,{data:e,embed:true}):null})}function Z({data:e,headerActions:t,footerActions:o}){let{t:n}=i18n.useTranslation(),r=e.sourceTweet,i=!!r,a=react.useMemo(()=>jsxRuntime.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[jsxRuntime.jsx("span",{children:n("mediaTrack.replyingTo")}),i&&jsxRuntime.jsxs(ui.Link,{className:"text-sm",underline:"hover",target:"_blank",href:utils.twitterUserUrl(r.user.screenName??r.user.username),children:["@",r.user.screenName??r.user.username]})]}),[i,r,n]);return jsxRuntime.jsx(u,{data:e,indicator:a,headerActions:t,footerActions:o,children:i?jsxRuntime.jsx(u,{data:e,embed:true}):null})}function J({data:e,headerActions:t,footerActions:o}){let{t:n}=i18n.useTranslation(),r=e.sourceTweet,i=!!r,a=react.useMemo(()=>jsxRuntime.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[jsxRuntime.jsx("span",{children:n("mediaTrack.retweetedBy")}),i&&jsxRuntime.jsxs(ui.Link,{className:"text-sm",underline:"hover",target:"_blank",href:utils.twitterUserUrl(r.user.screenName??r.user.username),children:["@",r.user.screenName??r.user.username]})]}),[i,r,n]);return jsxRuntime.jsx(u,{data:e,indicator:a,headerActions:t,footerActions:o,children:i?jsxRuntime.jsx(u,{data:e,embed:true}):null})}function K({data:e,headerActions:t,footerActions:o,embed:n=false,children:r,loading:i=false}){if(i||!e)return jsxRuntime.jsx(mt,{embed:n});let a=e.tweet.type;return jsxRuntime.jsx("div",{className:"w-full",children:(()=>{let d={data:e,headerActions:t,footerActions:o,embed:n,children:r};switch(a){case "reply":return jsxRuntime.jsx(Z,{...d});case "retweet":return jsxRuntime.jsx(J,{...d});case "quote":return jsxRuntime.jsx(Q,{...d});default:return jsxRuntime.jsx(D,{...d})}})()})}function mt({embed:e=false}){return jsxRuntime.jsxs("div",{className:["flex flex-col gap-2",e?"bg-default-50 rounded-lg p-3 w-full mx-auto":"bg-default-100 rounded-lg p-3 w-full mx-auto"].join(" "),children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-3",children:[jsxRuntime.jsx(ui.Skeleton,{className:"w-10 h-10 rounded-full"}),jsxRuntime.jsxs("div",{className:"flex flex-col gap-1 flex-1",children:[jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-24"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-3 w-16"})]}),jsxRuntime.jsx(ui.Skeleton,{className:"h-3 w-12"})]}),jsxRuntime.jsxs("div",{className:"flex flex-col gap-2",children:[jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-full"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-3/4"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-1/2"})]}),jsxRuntime.jsx(ui.Skeleton,{className:"h-48 w-full rounded-lg"}),jsxRuntime.jsxs("div",{className:"flex justify-between items-center pt-2",children:[jsxRuntime.jsxs("div",{className:"flex gap-4",children:[jsxRuntime.jsx(ui.Skeleton,{className:"h-6 w-16"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-6 w-16"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-6 w-16"})]}),jsxRuntime.jsx(ui.Skeleton,{className:"h-6 w-20"})]})]})}function xe({token:e}){let t=new utils.SafeBigNumber(e.priceChange??"0").isPositive()?"primary":"danger";return jsxRuntime.jsxs(ui.Button,{color:t,variant:"flat",size:"sm",radius:"full",startContent:jsxRuntime.jsx(ht,{token:e}),children:[jsxRuntime.jsx("span",{children:e.symbol}),jsxRuntime.jsx("span",{children:e.priceChange?utils.formatPercent(Number(e.priceChange)/100):"--"})]})}function ht({token:e}){let t=react.useMemo(()=>jsxRuntime.jsx(ui.Image,{className:"w-full h-full",src:e.image,alt:e.chain}),[e.chain,e.image]);return jsxRuntime.jsx(ui.Badge,{className:"w-2.5 h-2.5 p-0 border",size:"sm",content:t,shape:"circle",placement:"bottom-right",children:jsxRuntime.jsx(ui.Avatar,{className:"w-5 h-5",radius:"full",src:e.image})})}function Y({data:e,loading:t,setIsPaused:o,customHeaderActions:n,customFooterActions:r}){let i=react.useCallback(a=>jsxRuntime.jsxs("div",{className:"flex gap-2.5 justify-between",children:[a.token&&jsxRuntime.jsx(xe,{token:a.token}),r?.(a)]}),[r]);return jsxRuntime.jsx("div",{className:"flex flex-col gap-2.5",onMouseEnter:()=>o(true),onMouseLeave:()=>o(false),children:e.map(a=>jsxRuntime.jsx(K,{data:a,headerActions:n?.(a),footerActions:i(a),loading:t},a.id))})}function we(){return jsxRuntime.jsxs("div",{className:"flex flex-col gap-2 bg-default-100 rounded-lg p-3 w-full mx-auto",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-3",children:[jsxRuntime.jsx(ui.Skeleton,{className:"w-10 h-10 rounded-full"}),jsxRuntime.jsxs("div",{className:"flex flex-col gap-1 flex-1",children:[jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-40 rounded-md"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-3 w-32 rounded-md"})]})]}),jsxRuntime.jsxs("div",{className:"flex flex-col gap-2",children:[jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-full rounded-md"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-3/4 rounded-md"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-1/2 rounded-md"})]}),jsxRuntime.jsx(ui.Skeleton,{className:"h-48 w-full rounded-lg"})]})}function j({count:e=3}){return jsxRuntime.jsx("div",{className:"flex flex-col gap-2",children:Array.from({length:e}).map((t,o)=>jsxRuntime.jsx(we,{},o))})}var te=()=>{let[e,t]=react.useState([]),[o,n]=react.useState(true),[r,i]=react.useState(false),a=F(),l=react.useCallback(d=>{t(s=>{let c=s.findIndex(T=>T.id===d.id),m;if(c>=0)m=s.map((T,I)=>I===c?d:T);else {if(r)return s;m=[d,...s];}return m.slice(0,30)}),n(false);},[r]);return react.useEffect(()=>{let d=a.subscribe("x-monitor-basic",l),s=a.subscribe("x-monitor-token",l);return ()=>{d.unsubscribe(),s.unsubscribe();}},[a,l]),{medias:e,loading:o,isPaused:r,setIsPaused:i}};function Rt({onPauseChange:e,customHeaderActions:t,customFooterActions:o}){let{medias:n,loading:r,isPaused:i,setIsPaused:a}=te();return react.useEffect(()=>{e?.(i);},[i,e]),r?jsxRuntime.jsx(j,{count:3}):jsxRuntime.jsx(Y,{data:n,loading:r,setIsPaused:a,customHeaderActions:t,customFooterActions:o})}function re(){let e=0,t=false,o=null,n=new Map;return {get generation(){return e},connect(){e+=1,t=true;},disconnect(){t=false;},setLocaleTransform(r){o=r;},subscribe(r,i){let a=n.get(r);a||(a=new Set,n.set(r,a)),a.add(i);let l=false;return {unsubscribe(){if(l)return;l=true;let d=n.get(r);d?.delete(i),d&&d.size===0&&n.delete(r);}}},publish(r,i){if(!t)return;let a=o?o(i):i;n.get(r)?.forEach(l=>l(a));}}}function It({client:e,children:t}){let o=react.useMemo(()=>re(),[]);return jsxRuntime.jsx(N.Provider,{value:{client:e},children:jsxRuntime.jsxs(h.Provider,{value:o,children:[jsxRuntime.jsx(St,{client:e}),t]})})}function St({client:e}){let t=react.useContext(h);return react.useEffect(()=>{if(!t)return;t.connect();let o=e.subscribeTweetMedia({callback:r=>t.publish("x-monitor-basic",r)}),n=e.subscribeTweetMediaToken({callback:r=>t.publish("x-monitor-token",r)});return ()=>{o.unsubscribe(),n.unsubscribe(),t.disconnect();}},[e,t]),null}
1
+ 'use strict';var hooks=require('@liberfi.io/hooks'),ui=require('@liberfi.io/ui'),jsxRuntime=require('react/jsx-runtime'),utils=require('@liberfi.io/utils'),react=require('react'),i18n=require('@liberfi.io/i18n'),reactQuery=require('@tanstack/react-query');function S({src:e}){let[r,{setTrue:t}]=hooks.useBoolean(false);return e?jsxRuntime.jsx(ui.Skeleton,{isLoaded:r,className:"w-full h-auto",children:jsxRuntime.jsx("img",{src:e,className:"w-full h-full object-cover aspect-video",onLoad:()=>{t();}})}):null}function L({src:e}){return e?jsxRuntime.jsx("div",{className:"w-full h-full overflow-hidden rounded-md mt-2",children:jsxRuntime.jsx("iframe",{className:"w-full h-full aspect-video",src:e,allowFullScreen:true})}):null}function E({medias:e,tweetHref:r}){let t=e.filter(i=>i.type==="image"),n=e.filter(i=>i.type==="video"),o=()=>n.length?jsxRuntime.jsx("div",{className:"grid grid-cols-1 gap-[1px] overflow-hidden rounded-md",children:n.map(i=>jsxRuntime.jsx(L,{src:i.url},i.url))}):null,a=()=>t.length?jsxRuntime.jsx("div",{className:"grid grid-cols-1 gap-[1px] overflow-hidden rounded-md",children:t.map(i=>jsxRuntime.jsx(ui.Link,{href:r,target:"_blank",children:jsxRuntime.jsx(S,{src:i.url})},i.url))}):null;return jsxRuntime.jsxs("div",{className:"flex flex-col gap-2",children:[o(),a()]})}function U({url:e,name:r="",size:t=36}){let n=react.useMemo(()=>r?r.slice(0,2):"N/A",[r]);return jsxRuntime.jsx(ui.Skeleton,{className:"flex rounded-full flex-shrink-0",style:{width:t,height:t},isLoaded:!!e,children:jsxRuntime.jsx(ui.Avatar,{size:"md",color:"primary",radius:"full",showFallback:true,name:n,src:e,style:{width:t,height:t}})})}function B({user:e,renderTimestamp:r,renderActions:t}){return jsxRuntime.jsxs("div",{className:"flex items-center justify-between gap-1",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-1",children:[jsxRuntime.jsx(U,{url:e.avatar,name:e.username}),jsxRuntime.jsxs("div",{className:"flex flex-col gap-0.5",children:[jsxRuntime.jsxs("div",{className:"flex flex-row items-baseline gap-1",children:[jsxRuntime.jsx("span",{className:"text-foreground font-semibold truncate leading-none",children:e.username}),r]}),jsxRuntime.jsxs(ui.Link,{target:"_blank",underline:"hover",className:"text-text-muted text-sm leading-none",href:utils.twitterUserUrl(e.screenName??e.username),children:["@",e.screenName??e.username]})]})]}),t]})}var N=react.createContext({});var h=react.createContext(null);function O(){let e=react.useContext(N);if(!e)throw new Error("useMediaTrackContext must be used within a MediaTrackProvider");return e}function y(){let{client:e}=O();return e}function Ue(e={}){let r=y();return reactQuery.useMutation({mutationFn:async t=>r.generateMeme(t),...e})}function F(){let e=react.useContext(h);if(!e)throw new Error("useMediaTrackRuntime must be used within a MediaTrackProvider");return e}async function se(e,{media:r,targetLanguage:t,options:n}){return await e.translate(r,t,n)}function H(e={}){let r=y();return reactQuery.useMutation({mutationFn:async t=>se(r,t),...e})}function R(e){let r=/(https?:\/\/[^\s]+|www\.[^\s]+)/gi,t=/#[\w]+/g,n=/\$[A-Za-z][A-Za-z0-9_]*/g,o=[],a;for(;(a=r.exec(e))!==null;)o.push({index:a.index,length:a[0].length,text:a[0],type:"url"});for(;(a=t.exec(e))!==null;){let s=a.index;o.some(m=>s>=m.index&&s<m.index+m.length)||o.push({index:s,length:a[0].length,text:a[0],type:"hashtag"});}for(;(a=n.exec(e))!==null;){let s=a.index;o.some(m=>s>=m.index&&s<m.index+m.length)||o.push({index:s,length:a[0].length,text:a[0],type:"symbol"});}o.sort((s,c)=>s.index-c.index);let i=[],l=0,d=0;return o.forEach(s=>{if(s.index>l&&i.push(e.slice(l,s.index)),s.type==="url"){let c=s.text.startsWith("http")?s.text:`https://${s.text}`;i.push(jsxRuntime.jsx("a",{href:c,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",onClick:m=>m.stopPropagation(),children:s.text},d++));}else if(s.type==="hashtag"){let m=`https://x.com/hashtag/${s.text.slice(1)}`;i.push(jsxRuntime.jsx("a",{href:m,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",onClick:T=>T.stopPropagation(),children:s.text},d++));}else s.type==="symbol"&&i.push(jsxRuntime.jsx("span",{className:"text-primary",children:s.text},d++));l=s.index+s.length;}),l<e.length&&i.push(e.slice(l)),i.length>0?i:[e]}function W({data:e,embed:r,renderActions:t}){let[n,{toggle:o}]=hooks.useBoolean(false),{t:a,i18n:i}=i18n.useTranslation(),{mutateAsync:l,isPending:d}=H(),[s,c]=react.useState(null),m=react.useCallback(async T=>{if(T.stopPropagation(),o(),!s){let I=await l({media:e,targetLanguage:i.language,options:{sourceTweet:r}}),Me=R(I);c(Me);}},[o,l,e,i.language,s,r]);return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-1 text-xs",children:[jsxRuntime.jsxs("div",{onClick:m,className:"flex items-center gap-0.5 cursor-pointer text-primary hover:text-foreground",children:[jsxRuntime.jsx(ui.TranslateIcon,{width:"14",height:"14"}),a(n?"mediaTrack.tweets.translate.hide":"mediaTrack.tweets.translate.show")]}),t]}),jsxRuntime.jsx("div",{className:ui.cn(!n&&"hidden"),onClick:T=>{T.stopPropagation();},children:n&&jsxRuntime.jsxs("div",{className:"bg-content2 rounded-md p-2 text-text-primary text-sm leading-5",children:[s,d&&jsxRuntime.jsx(ui.Skeleton,{className:"w-full h-4 rounded-md"})]})})]})}function G({isExpanded:e,onToggleExpand:r}){let{t}=i18n.useTranslation(),n=()=>e?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(ui.ChevronUpIcon,{className:"border border-current",width:"12",height:"12"}),"\xA0",t("mediaTrack.tweets.collapse")]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(ui.ChevronDownIcon,{className:"border border-current",width:"12",height:"12"}),"\xA0",t("mediaTrack.tweets.expand")]});return e===void 0?null:jsxRuntime.jsxs("div",{className:"flex items-center gap-1",children:[jsxRuntime.jsx("div",{className:"w-px h-2.5 bg-line-300"}),jsxRuntime.jsx("button",{onClick:o=>{o.stopPropagation(),r?.(!e);},className:"flex items-center text-text-muted hover:text-foreground text-xs",children:n()})]})}function de({content:e,isExpanded:r=false,onLoad:t}){let n=react.useRef(null),o=react.useMemo(()=>R(e),[e]);return react.useEffect(()=>{let a=n.current;!t||!a||a.scrollHeight>a.clientHeight&&t?.();},[r,t]),jsxRuntime.jsx("div",{ref:n,className:["text-text-primary text-sm leading-5",r?"":"line-clamp-3"].join(" "),onClick:a=>{a.stopPropagation();},children:o})}function u({data:e,headerActions:r,footerActions:t,embed:n=false,indicator:o,children:a}){let{formatAge:i}=i18n.useLocalizedTimeFormatter(),[l,d]=react.useState(void 0),s=react.useMemo(()=>n?"bg-default-50 rounded-lg p-3 w-full mx-auto":"bg-default-100 hover:bg-default-200 rounded-lg p-3 w-full mx-auto",[n]),c=react.useMemo(()=>n?e.sourceTweet:e.tweet,[e,n]),m=hooks.useTickAge(c.timestamp);return jsxRuntime.jsxs("div",{className:ui.cn("flex flex-col gap-1.5 cursor-pointer",s),onClick:()=>{window.open(utils.twitterTweetUrl(c.tweetId),"_blank");},children:[jsxRuntime.jsx(B,{user:c.user,renderTimestamp:n?void 0:jsxRuntime.jsx("div",{className:"text-xs text-primary",children:i(m)}),renderActions:r}),o,c.content.text&&jsxRuntime.jsx(de,{content:c.content.text,isExpanded:l,onLoad:()=>d(false)}),c.content.text&&jsxRuntime.jsx(W,{data:e,embed:n,text:c.content.text,renderActions:jsxRuntime.jsx(G,{isExpanded:l,onToggleExpand:d})}),jsxRuntime.jsx("div",{className:ui.cn((!c.content.medias||c.content.medias.length===0)&&"hidden"),children:c.content.medias&&c.content.medias.length>0&&jsxRuntime.jsx(E,{medias:c.content.medias,tweetHref:utils.twitterTweetUrl(c.tweetId)})}),a,t]})}function D({data:e,headerActions:r,footerActions:t}){return jsxRuntime.jsx(u,{data:e,headerActions:r,footerActions:t})}function Q({data:e,headerActions:r,footerActions:t}){let o=!!e.sourceTweet;return jsxRuntime.jsx(u,{data:e,headerActions:r,footerActions:t,children:o?jsxRuntime.jsx(u,{data:e,embed:true}):null})}function Z({data:e,headerActions:r,footerActions:t}){let{t:n}=i18n.useTranslation(),o=e.sourceTweet,a=!!o,i=react.useMemo(()=>jsxRuntime.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[jsxRuntime.jsx("span",{children:n("mediaTrack.replyingTo")}),a&&jsxRuntime.jsxs(ui.Link,{className:"text-sm",underline:"hover",target:"_blank",href:utils.twitterUserUrl(o.user.screenName??o.user.username),children:["@",o.user.screenName??o.user.username]})]}),[a,o,n]);return jsxRuntime.jsx(u,{data:e,indicator:i,headerActions:r,footerActions:t,children:a?jsxRuntime.jsx(u,{data:e,embed:true}):null})}function J({data:e,headerActions:r,footerActions:t}){let{t:n}=i18n.useTranslation(),o=e.sourceTweet,a=!!o,i=react.useMemo(()=>jsxRuntime.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[jsxRuntime.jsx("span",{children:n("mediaTrack.retweetedBy")}),a&&jsxRuntime.jsxs(ui.Link,{className:"text-sm",underline:"hover",target:"_blank",href:utils.twitterUserUrl(o.user.screenName??o.user.username),children:["@",o.user.screenName??o.user.username]})]}),[a,o,n]);return jsxRuntime.jsx(u,{data:e,indicator:i,headerActions:r,footerActions:t,children:a?jsxRuntime.jsx(u,{data:e,embed:true}):null})}function K({data:e,headerActions:r,footerActions:t,embed:n=false,children:o,loading:a=false}){if(a||!e)return jsxRuntime.jsx(mt,{embed:n});let i=e.tweet.type;return jsxRuntime.jsx("div",{className:"w-full",children:(()=>{let d={data:e,headerActions:r,footerActions:t,embed:n,children:o};switch(i){case "reply":return jsxRuntime.jsx(Z,{...d});case "retweet":return jsxRuntime.jsx(J,{...d});case "quote":return jsxRuntime.jsx(Q,{...d});default:return jsxRuntime.jsx(D,{...d})}})()})}function mt({embed:e=false}){return jsxRuntime.jsxs("div",{className:["flex flex-col gap-2",e?"bg-default-50 rounded-lg p-3 w-full mx-auto":"bg-default-100 rounded-lg p-3 w-full mx-auto"].join(" "),children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-3",children:[jsxRuntime.jsx(ui.Skeleton,{className:"w-10 h-10 rounded-full"}),jsxRuntime.jsxs("div",{className:"flex flex-col gap-1 flex-1",children:[jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-24"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-3 w-16"})]}),jsxRuntime.jsx(ui.Skeleton,{className:"h-3 w-12"})]}),jsxRuntime.jsxs("div",{className:"flex flex-col gap-2",children:[jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-full"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-3/4"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-1/2"})]}),jsxRuntime.jsx(ui.Skeleton,{className:"h-48 w-full rounded-lg"}),jsxRuntime.jsxs("div",{className:"flex justify-between items-center pt-2",children:[jsxRuntime.jsxs("div",{className:"flex gap-4",children:[jsxRuntime.jsx(ui.Skeleton,{className:"h-6 w-16"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-6 w-16"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-6 w-16"})]}),jsxRuntime.jsx(ui.Skeleton,{className:"h-6 w-20"})]})]})}function xe({token:e}){let r=new utils.SafeBigNumber(e.priceChange??"0").isPositive()?"primary":"danger";return jsxRuntime.jsxs(ui.Button,{color:r,variant:"flat",size:"sm",radius:"full",startContent:jsxRuntime.jsx(ht,{token:e}),children:[jsxRuntime.jsx("span",{children:e.symbol}),jsxRuntime.jsx("span",{children:e.priceChange?utils.formatPercent(Number(e.priceChange)/100):"--"})]})}function ht({token:e}){let r=react.useMemo(()=>jsxRuntime.jsx(ui.Image,{className:"w-full h-full",src:e.image,alt:e.chain}),[e.chain,e.image]);return jsxRuntime.jsx(ui.Badge,{className:"w-2.5 h-2.5 p-0 border",size:"sm",content:r,shape:"circle",placement:"bottom-right",children:jsxRuntime.jsx(ui.Avatar,{className:"w-5 h-5",radius:"full",src:e.image})})}function Y({data:e,loading:r,setIsPaused:t,customHeaderActions:n,customFooterActions:o}){let a=react.useCallback(i=>jsxRuntime.jsxs("div",{className:"flex gap-2.5 justify-between",children:[i.token&&jsxRuntime.jsx(xe,{token:i.token}),o?.(i)]}),[o]);return jsxRuntime.jsx("div",{className:"flex flex-col gap-2.5",onMouseEnter:()=>t(true),onMouseLeave:()=>t(false),children:e.map(i=>jsxRuntime.jsx(K,{data:i,headerActions:n?.(i),footerActions:a(i),loading:r},i.id))})}function we(){return jsxRuntime.jsxs("div",{className:"flex flex-col gap-2 bg-default-100 rounded-lg p-3 w-full mx-auto",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-3",children:[jsxRuntime.jsx(ui.Skeleton,{className:"w-10 h-10 rounded-full"}),jsxRuntime.jsxs("div",{className:"flex flex-col gap-1 flex-1",children:[jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-40 rounded-md"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-3 w-32 rounded-md"})]})]}),jsxRuntime.jsxs("div",{className:"flex flex-col gap-2",children:[jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-full rounded-md"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-3/4 rounded-md"}),jsxRuntime.jsx(ui.Skeleton,{className:"h-4 w-1/2 rounded-md"})]}),jsxRuntime.jsx(ui.Skeleton,{className:"h-48 w-full rounded-lg"})]})}function j({count:e=3}){return jsxRuntime.jsx("div",{className:"flex flex-col gap-2",children:Array.from({length:e}).map((r,t)=>jsxRuntime.jsx(we,{},t))})}var te=()=>{let[e,r]=react.useState([]),[t,n]=react.useState(true),[o,a]=react.useState(false),i=F(),l=react.useCallback(d=>{r(s=>{let c=s.findIndex(T=>T.id===d.id),m;if(c>=0)m=s.map((T,I)=>I===c?d:T);else {if(o)return s;m=[d,...s];}return m.slice(0,30)}),n(false);},[o]);return react.useEffect(()=>{let d=i.subscribe("x-monitor-basic",l),s=i.subscribe("x-monitor-token",l);return ()=>{d.unsubscribe(),s.unsubscribe();}},[i,l]),{medias:e,loading:t,isPaused:o,setIsPaused:a}};function Rt({onPauseChange:e,customHeaderActions:r,customFooterActions:t}){let{medias:n,loading:o,isPaused:a,setIsPaused:i}=te();return react.useEffect(()=>{e?.(a);},[a,e]),o?jsxRuntime.jsx(j,{count:3}):jsxRuntime.jsx(Y,{data:n,loading:o,setIsPaused:i,customHeaderActions:r,customFooterActions:t})}function re(){let e=0,r=false,t=null,n=new Map;return {get generation(){return e},connect(){e+=1,r=true;},disconnect(){r=false;},setLocaleTransform(o){t=o;},subscribe(o,a){let i=n.get(o);i||(i=new Set,n.set(o,i)),i.add(a);let l=false;return {unsubscribe(){if(l)return;l=true;let d=n.get(o);d?.delete(a),d&&d.size===0&&n.delete(o);}}},publish(o,a){if(!r)return;let i=t?t(a):a;n.get(o)?.forEach(l=>l(i));}}}function It({client:e,children:r,active:t=true}){let n=react.useMemo(()=>re(),[]);return jsxRuntime.jsx(N.Provider,{value:{client:e},children:jsxRuntime.jsxs(h.Provider,{value:n,children:[jsxRuntime.jsx(St,{client:e,active:t}),r]})})}function St({client:e,active:r}){let t=react.useContext(h);return react.useEffect(()=>{if(!t||!r)return;t.connect();let n=e.subscribeTweetMedia({callback:a=>t.publish("x-monitor-basic",a)}),o=e.subscribeTweetMediaToken({callback:a=>t.publish("x-monitor-token",a)});return ()=>{n.unsubscribe(),o.unsubscribe(),t.disconnect(),e.disconnect();}},[r,e,t]),null}
2
2
  exports.MediaImage=S;exports.MediaTrackContext=N;exports.MediaTrackProvider=It;exports.MediaTrackRuntimeContext=h;exports.MediaVideo=L;exports.Medias=E;exports.TextExpand=G;exports.Translate=W;exports.TweetItem=K;exports.TweetOriginal=D;exports.TweetQuote=Q;exports.TweetReply=Z;exports.TweetRetweet=J;exports.TweetSkeleton=we;exports.TweetSkeletonList=j;exports.TweetSource=u;exports.Tweets=Y;exports.TweetsWidget=Rt;exports.UserAvatar=U;exports.UserInfo=B;exports.createMediaTrackRuntime=re;exports.translateTweetMedia=se;exports.useGenerateTweetMediaMemeMutation=Ue;exports.useMediaTrackClient=y;exports.useMediaTrackContext=O;exports.useMediaTrackRuntime=F;exports.useTranslateTweetMediaMutation=H;exports.useTweets=te;//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/tweets/tweet/media/media-image.tsx","../src/components/tweets/tweet/media/media-video.tsx","../src/components/tweets/tweet/media/medias.tsx","../src/components/tweets/tweet/user/user-avatar.tsx","../src/components/tweets/tweet/user/user-info.tsx","../src/context/MediaTrackContext.ts","../src/context/MediaTrackRuntimeContext.ts","../src/hooks/useMediaTrackContext.ts","../src/hooks/useMediaTrackClient.ts","../src/hooks/useGenerateTweetMediaMemeMutation.ts","../src/hooks/useMediaTrackRuntime.ts","../src/hooks/useTranslateTweetMediaQuery.ts","../src/utils/parseText.tsx","../src/components/tweets/tweet/tools/translate.tsx","../src/components/tweets/tweet/tools/text-expand.tsx","../src/components/tweets/tweet/content/index.tsx","../src/components/tweets/tweet/tweet-source.tsx","../src/components/tweets/tweet/tweet-original.tsx","../src/components/tweets/tweet/tweet-quote.tsx","../src/components/tweets/tweet/tweet-reply.tsx","../src/components/tweets/tweet/tweet-retweet.tsx","../src/components/tweets/tweet/tweet-item.tsx","../src/components/tweets/tweet/tools/tweet-token-button.tsx","../src/components/tweets/tweets.ui.tsx","../src/components/tweets/tweet/tweet-skeleton.tsx","../src/components/tweets/tweets.script.ts","../src/components/tweets/tweets.widget.tsx","../src/runtime/media-track-runtime.ts","../src/providers/MediaTrackProvider.tsx"],"names":["MediaImage","src","isLoaded","setTrue","useBoolean","jsx","Skeleton","MediaVideo","Medias","medias","tweetHref","images","media","videos","renderVideos","video","renderImages","image","Link","jsxs","UserAvatar","url","name","size","fallbackName","useMemo","Avatar","UserInfo","user","renderTimestamp","renderActions","twitterUserUrl","MediaTrackContext","createContext","MediaTrackRuntimeContext","useMediaTrackContext","context","useContext","useMediaTrackClient","client","useGenerateTweetMediaMemeMutation","options","useMutation","params","useMediaTrackRuntime","runtime","translateTweetMedia","targetLanguage","useTranslateTweetMediaMutation","parseText","text","urlRegex","hashtagRegex","symbolRegex","matches","match","matchIndex","a","b","parts","lastIndex","key","item","e","hashtagUrl","Translate","data","embed","isTranslate","toggle","t","i18n","useTranslation","isTranslating","translatedText","setTranslatedText","useState","handleTranslate","useCallback","parsedText","Fragment","TranslateIcon","cn","TextExpand","isExpanded","onToggleExpand","renderExpand","ChevronUpIcon","ChevronDownIcon","Content","content","onLoad","ref","useRef","parsedContent","useEffect","current","TweetSource","headerActions","footerActions","indicator","children","formatAge","useLocalizedTimeFormatter","setIsExpanded","containerClass","tweet","age","useTickAge","twitterTweetUrl","TweetOriginal","TweetQuote","hasSource","TweetReply","sourceTweet","TweetRetweet","TweetItem","loading","TweetSkeleton","tweetType","commonProps","TweetTokenButton","token","color","SafeBigNumber","Button","TweetTokenIcon","formatPercent","ChainIcon","Image","Badge","Tweets","setIsPaused","customHeaderActions","customFooterActions","TweetSkeletonList","count","_","index","useTweets","setMedias","setLoading","isPaused","handleMedia","prevMedias","idx","it","newMedias","subTweet","subTweetToken","TweetsWidget","onPauseChange","createMediaTrackRuntime","generation","connected","localeTransform","listeners","transform","channel","listener","bucket","unsubscribed","payload","next","MediaTrackProvider","MediaTrackClientBridge","basic"],"mappings":"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","file":"index.js","sourcesContent":["import { useBoolean } from \"@liberfi.io/hooks\";\nimport { Skeleton } from \"@liberfi.io/ui\";\n\ntype Props = {\n src: string;\n};\n\n// ------------------------------------------------------------\nexport function MediaImage({ src }: Props) {\n const [isLoaded, { setTrue }] = useBoolean(false);\n if (!src) return null;\n\n return (\n <Skeleton isLoaded={isLoaded} className=\"w-full h-auto\">\n <img\n src={src}\n className=\"w-full h-full object-cover aspect-video\"\n onLoad={() => {\n setTrue();\n }}\n />\n </Skeleton>\n );\n}\n","type Props = {\n src: string;\n};\n\n// ------------------------------------------------------------\nexport function MediaVideo({ src }: Props) {\n if (!src) return null;\n\n return (\n <div className=\"w-full h-full overflow-hidden rounded-md mt-2\">\n <iframe\n className=\"w-full h-full aspect-video\"\n src={src}\n allowFullScreen\n />\n </div>\n );\n}\n","import { Link } from \"@liberfi.io/ui\";\nimport { TweetContentMedia } from \"../../../../types\";\nimport { MediaImage } from \"./media-image\";\nimport { MediaVideo } from \"./media-video\";\n\ntype Props = {\n medias: Array<TweetContentMedia>;\n tweetHref: string;\n};\n\nexport function Medias({ medias, tweetHref }: Props) {\n const images = medias.filter((media) => media.type === \"image\");\n const videos = medias.filter((media) => media.type === \"video\");\n\n const renderVideos = () => {\n if (!videos.length) return null;\n return (\n <div className={`grid grid-cols-1 gap-[1px] overflow-hidden rounded-md`}>\n {videos.map((video) => (\n <MediaVideo key={video.url} src={video.url} />\n ))}\n </div>\n );\n };\n\n const renderImages = () => {\n if (!images.length) return null;\n return (\n <div className={`grid grid-cols-1 gap-[1px] overflow-hidden rounded-md`}>\n {images.map((image) => (\n <Link key={image.url} href={tweetHref} target=\"_blank\">\n <MediaImage src={image.url} />\n </Link>\n ))}\n </div>\n );\n };\n\n return (\n <div className=\"flex flex-col gap-2\">\n {renderVideos()}\n {renderImages()}\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { Avatar, Skeleton } from \"@liberfi.io/ui\";\n\ntype Props = {\n url?: string;\n name?: string;\n size?: number;\n};\n\nexport function UserAvatar({ url, name = \"\", size = 36 }: Props) {\n const fallbackName = useMemo(() => (name ? name.slice(0, 2) : \"N/A\"), [name]);\n\n return (\n <Skeleton\n className=\"flex rounded-full flex-shrink-0\"\n style={{ width: size, height: size }}\n isLoaded={!!url}\n >\n <Avatar\n size=\"md\"\n color=\"primary\"\n radius=\"full\"\n showFallback\n name={fallbackName}\n src={url}\n style={{ width: size, height: size }}\n />\n </Skeleton>\n );\n}\n","import React from \"react\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetUser } from \"../../../../types\";\nimport { UserAvatar } from \"./user-avatar\";\n\ntype Props = {\n user: TweetUser;\n renderTimestamp?: React.ReactNode;\n renderActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function UserInfo({ user, renderTimestamp, renderActions }: Props) {\n return (\n <div className=\"flex items-center justify-between gap-1\">\n <div className=\"flex items-center gap-1\">\n <UserAvatar url={user.avatar} name={user.username} />\n <div className=\"flex flex-col gap-0.5\">\n <div className=\"flex flex-row items-baseline gap-1\">\n <span className=\"text-foreground font-semibold truncate leading-none\">\n {user.username}\n </span>\n {renderTimestamp}\n </div>\n <Link\n target=\"_blank\"\n underline=\"hover\"\n className=\"text-text-muted text-sm leading-none\"\n href={twitterUserUrl(user.screenName ?? user.username)}\n >\n @{user.screenName ?? user.username}\n </Link>\n </div>\n </div>\n {renderActions}\n </div>\n );\n}\n","import { createContext } from \"react\";\nimport { IMediaTrackClient } from \"../types\";\n\nexport interface MediaTrackContextValue {\n client: IMediaTrackClient;\n}\n\nexport const MediaTrackContext = createContext<MediaTrackContextValue>(\n {} as MediaTrackContextValue,\n);\n","import { createContext } from \"react\";\nimport type { TweetMedia } from \"../types\";\nimport type { MediaTrackRuntime } from \"../runtime/media-track-runtime\";\n\nexport const MediaTrackRuntimeContext =\n createContext<MediaTrackRuntime<TweetMedia> | null>(null);\n","import { useContext } from \"react\";\nimport { MediaTrackContext } from \"../context\";\n\nexport function useMediaTrackContext() {\n const context = useContext(MediaTrackContext);\n if (!context) {\n throw new Error(\n \"useMediaTrackContext must be used within a MediaTrackProvider\",\n );\n }\n return context;\n}\n","import { useMediaTrackContext } from \"./useMediaTrackContext\";\n\nexport function useMediaTrackClient() {\n const { client } = useMediaTrackContext();\n return client;\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport { GeneratedMemeInfo, TweetMedia } from \"../types\";\nimport { useMediaTrackClient } from \"./useMediaTrackClient\";\n\nexport function useGenerateTweetMediaMemeMutation(\n options: Omit<\n UseMutationOptions<GeneratedMemeInfo, Error, TweetMedia, string[]>,\n \"mutationFn\"\n > = {},\n) {\n const client = useMediaTrackClient();\n return useMutation({\n mutationFn: async (params: TweetMedia) => client.generateMeme(params),\n ...options,\n });\n}\n","import { useContext } from \"react\";\nimport { MediaTrackRuntimeContext } from \"../context/MediaTrackRuntimeContext\";\n\nexport function useMediaTrackRuntime() {\n const runtime = useContext(MediaTrackRuntimeContext);\n if (!runtime) {\n throw new Error(\n \"useMediaTrackRuntime must be used within a MediaTrackProvider\",\n );\n }\n return runtime;\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport { LocaleCode } from \"@liberfi.io/i18n\";\nimport { IMediaTrackClient, TweetMedia } from \"../types\";\nimport { useMediaTrackClient } from \"./useMediaTrackClient\";\n\nexport interface UseTranslateTweetMediaParams {\n media: TweetMedia;\n targetLanguage: LocaleCode;\n options?: {\n sourceLanguage?: LocaleCode;\n sourceTweet?: boolean;\n };\n}\n\nexport async function translateTweetMedia(\n client: IMediaTrackClient,\n { media, targetLanguage, options }: UseTranslateTweetMediaParams,\n) {\n return await client.translate(media, targetLanguage, options);\n}\n\nexport function useTranslateTweetMediaMutation(\n options: Omit<\n UseMutationOptions<string, Error, UseTranslateTweetMediaParams>,\n \"mutationFn\"\n > = {},\n) {\n const client = useMediaTrackClient();\n return useMutation({\n mutationFn: async (params: UseTranslateTweetMediaParams) =>\n translateTweetMedia(client, params),\n ...options,\n });\n}\n","interface MatchItem {\n index: number;\n length: number;\n text: string;\n type: \"url\" | \"hashtag\" | \"symbol\";\n}\n\nexport function parseText(text: string): (string | React.ReactElement)[] {\n const urlRegex = /(https?:\\/\\/[^\\s]+|www\\.[^\\s]+)/gi;\n const hashtagRegex = /#[\\w]+/g;\n const symbolRegex = /\\$[A-Za-z][A-Za-z0-9_]*/g;\n\n const matches: MatchItem[] = [];\n let match: RegExpExecArray | null;\n\n while ((match = urlRegex.exec(text)) !== null) {\n matches.push({\n index: match.index,\n length: match[0].length,\n text: match[0],\n type: \"url\",\n });\n }\n\n while ((match = hashtagRegex.exec(text)) !== null) {\n const matchIndex = match.index;\n const overlaps = matches.some(\n (m) => matchIndex >= m.index && matchIndex < m.index + m.length,\n );\n if (!overlaps) {\n matches.push({\n index: matchIndex,\n length: match[0].length,\n text: match[0],\n type: \"hashtag\",\n });\n }\n }\n\n while ((match = symbolRegex.exec(text)) !== null) {\n const matchIndex = match.index;\n const overlaps = matches.some(\n (m) => matchIndex >= m.index && matchIndex < m.index + m.length,\n );\n if (!overlaps) {\n matches.push({\n index: matchIndex,\n length: match[0].length,\n text: match[0],\n type: \"symbol\",\n });\n }\n }\n\n matches.sort((a, b) => a.index - b.index);\n\n const parts: (string | React.ReactElement)[] = [];\n let lastIndex = 0;\n let key = 0;\n\n matches.forEach((item) => {\n if (item.index > lastIndex) {\n parts.push(text.slice(lastIndex, item.index));\n }\n\n if (item.type === \"url\") {\n const url = item.text.startsWith(\"http\")\n ? item.text\n : `https://${item.text}`;\n parts.push(\n <a\n key={key++}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n onClick={(e) => e.stopPropagation()}\n >\n {item.text}\n </a>,\n );\n } else if (item.type === \"hashtag\") {\n const hashtag = item.text.slice(1); // 移除 #\n const hashtagUrl = `https://x.com/hashtag/${hashtag}`;\n parts.push(\n <a\n key={key++}\n href={hashtagUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n onClick={(e) => e.stopPropagation()}\n >\n {item.text}\n </a>,\n );\n } else if (item.type === \"symbol\") {\n parts.push(\n <span key={key++} className=\"text-primary\">\n {item.text}\n </span>,\n );\n }\n\n lastIndex = item.index + item.length;\n });\n\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n\n return parts.length > 0 ? parts : [text];\n}\n","import React, { MouseEvent, useCallback, useState } from \"react\";\nimport { useBoolean } from \"@liberfi.io/hooks\";\nimport { LocaleCode, useTranslation } from \"@liberfi.io/i18n\";\nimport { cn, Skeleton, TranslateIcon } from \"@liberfi.io/ui\";\nimport { useTranslateTweetMediaMutation } from \"../../../../hooks\";\nimport { TweetMedia } from \"../../../../types\";\nimport { parseText } from \"../../../../utils\";\n\ntype Props = {\n data: TweetMedia;\n embed?: boolean;\n text: string;\n renderActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function Translate({ data, embed, renderActions }: Props) {\n const [isTranslate, { toggle }] = useBoolean(false);\n\n const { t, i18n } = useTranslation();\n\n const { mutateAsync: translateTweetMedia, isPending: isTranslating } =\n useTranslateTweetMediaMutation();\n\n const [translatedText, setTranslatedText] = useState<\n (string | React.ReactElement)[] | null\n >(null);\n\n const handleTranslate = useCallback(\n async (e: MouseEvent<HTMLDivElement>) => {\n e.stopPropagation();\n toggle();\n if (!translatedText) {\n const text = await translateTweetMedia({\n media: data,\n targetLanguage: i18n.language as LocaleCode,\n options: {\n sourceTweet: embed,\n },\n });\n const parsedText = parseText(text);\n setTranslatedText(parsedText);\n }\n },\n [toggle, translateTweetMedia, data, i18n.language, translatedText, embed],\n );\n\n return (\n <>\n <div className=\"flex items-center gap-1 text-xs\">\n <div\n onClick={handleTranslate}\n className=\"flex items-center gap-0.5 cursor-pointer text-primary hover:text-foreground\"\n >\n <TranslateIcon width=\"14\" height=\"14\" />\n {isTranslate\n ? t(\"mediaTrack.tweets.translate.hide\")\n : t(\"mediaTrack.tweets.translate.show\")}\n </div>\n {renderActions}\n </div>\n <div\n className={cn(!isTranslate && \"hidden\")}\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n {isTranslate && (\n <div className=\"bg-content2 rounded-md p-2 text-text-primary text-sm leading-5\">\n {translatedText}\n {isTranslating && <Skeleton className=\"w-full h-4 rounded-md\" />}\n </div>\n )}\n </div>\n </>\n );\n}\n","import { useTranslation } from \"@liberfi.io/i18n\";\nimport { ChevronDownIcon, ChevronUpIcon } from \"@liberfi.io/ui\";\n\ntype Props = {\n isExpanded?: boolean;\n onToggleExpand?: (expanded: boolean) => void;\n};\n\nexport function TextExpand({ isExpanded, onToggleExpand }: Props) {\n const { t } = useTranslation();\n const renderExpand = () => {\n if (isExpanded) {\n return (\n <>\n <ChevronUpIcon\n className=\"border border-current\"\n width=\"12\"\n height=\"12\"\n />\n &nbsp;{t(\"mediaTrack.tweets.collapse\")}\n </>\n );\n }\n\n return (\n <>\n <ChevronDownIcon\n className=\"border border-current\"\n width=\"12\"\n height=\"12\"\n />\n &nbsp;{t(\"mediaTrack.tweets.expand\")}\n </>\n );\n };\n\n if (isExpanded === undefined) return null;\n\n return (\n <div className=\"flex items-center gap-1\">\n <div className=\"w-px h-2.5 bg-line-300\" />\n <button\n onClick={(e) => {\n e.stopPropagation();\n onToggleExpand?.(!isExpanded);\n }}\n className=\"flex items-center text-text-muted hover:text-foreground text-xs\"\n >\n {renderExpand()}\n </button>\n </div>\n );\n}\n","import { useEffect, useMemo, useRef } from \"react\";\nimport { parseText } from \"../../../../utils\";\n\ntype Props = {\n content: string;\n isExpanded?: boolean;\n onLoad?: () => void;\n};\n\n// ------------------------------------------------------------\nexport function Content({ content, isExpanded = false, onLoad }: Props) {\n const ref = useRef<HTMLDivElement>(null);\n\n const parsedContent = useMemo(() => parseText(content), [content]);\n\n useEffect(() => {\n const current = ref.current;\n if (!onLoad || !current) return;\n if (current.scrollHeight > current.clientHeight) {\n onLoad?.();\n }\n }, [isExpanded, onLoad]);\n\n return (\n <div\n ref={ref}\n className={[\n \"text-text-primary text-sm leading-5\",\n !isExpanded ? \"line-clamp-3\" : \"\",\n ].join(\" \")}\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n {parsedContent}\n </div>\n );\n}\n","import React, { useMemo, useState } from \"react\";\nimport { useTickAge } from \"@liberfi.io/hooks\";\nimport { useLocalizedTimeFormatter } from \"@liberfi.io/i18n\";\nimport { cn } from \"@liberfi.io/ui\";\nimport { twitterTweetUrl } from \"@liberfi.io/utils\";\nimport { Tweet, TweetMedia } from \"../../../types\";\nimport { Content } from \"./content\";\nimport { Medias } from \"./media\";\nimport { Translate, TextExpand } from \"./tools\";\nimport { UserInfo } from \"./user\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n embed?: boolean;\n indicator?: React.ReactNode;\n children?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetSource({\n data,\n headerActions,\n footerActions,\n embed = false,\n indicator,\n children,\n}: Props) {\n const { formatAge } = useLocalizedTimeFormatter();\n const [isExpanded, setIsExpanded] = useState<boolean | undefined>(undefined);\n\n const containerClass = useMemo(() => {\n return embed\n ? \"bg-default-50 rounded-lg p-3 w-full mx-auto\"\n : \"bg-default-100 hover:bg-default-200 rounded-lg p-3 w-full mx-auto\";\n }, [embed]);\n\n const tweet = useMemo(\n () => (embed ? data.sourceTweet! : data.tweet),\n [data, embed],\n );\n\n const age = useTickAge((tweet as Tweet).timestamp);\n\n return (\n <div\n className={cn(\"flex flex-col gap-1.5 cursor-pointer\", containerClass)}\n onClick={() => {\n window.open(twitterTweetUrl(tweet.tweetId), \"_blank\");\n }}\n >\n {/* -------- USER INFO -------- */}\n <UserInfo\n user={tweet.user}\n renderTimestamp={\n embed ? undefined : (\n <div className=\"text-xs text-primary\">{formatAge(age)}</div>\n )\n }\n renderActions={headerActions}\n />\n\n {/* -------- MESSAGE TYPE INDICATOR -------- */}\n {indicator}\n\n {/* -------- CONTENT -------- */}\n {tweet.content.text && (\n <Content\n content={tweet.content.text}\n isExpanded={isExpanded}\n onLoad={() => setIsExpanded(false)}\n />\n )}\n\n {/* -------- TOOLS -------- */}\n {tweet.content.text && (\n <Translate\n data={data}\n embed={embed}\n text={tweet.content.text}\n renderActions={\n <TextExpand\n isExpanded={isExpanded}\n onToggleExpand={setIsExpanded}\n />\n }\n />\n )}\n\n {/* -------- MEDIA -------- */}\n <div\n className={cn(\n (!tweet.content.medias || tweet.content.medias.length === 0) &&\n \"hidden\",\n )}\n >\n {tweet.content.medias && tweet.content.medias.length > 0 && (\n <Medias\n medias={tweet.content.medias}\n tweetHref={twitterTweetUrl(tweet.tweetId)}\n />\n )}\n </div>\n\n {/* -------- CHILDREN -------- */}\n {children}\n\n {/* -------- Custom ACTIONS -------- */}\n {footerActions}\n </div>\n );\n}\n","import React from \"react\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetOriginal({ data, headerActions, footerActions }: Props) {\n return (\n <TweetSource\n data={data}\n headerActions={headerActions}\n footerActions={footerActions}\n />\n );\n}\n","import React from \"react\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetQuote({ data, headerActions, footerActions }: Props) {\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n return (\n <TweetSource\n data={data}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React, { useMemo } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetReply({ data, headerActions, footerActions }: Props) {\n const { t } = useTranslation();\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n const indicator = useMemo(\n () => (\n <div className=\"flex items-center gap-2 text-sm\">\n <span>{t(\"mediaTrack.replyingTo\")}</span>\n {hasSource && (\n <Link\n className=\"text-sm\"\n underline=\"hover\"\n target=\"_blank\"\n href={twitterUserUrl(\n sourceTweet.user.screenName ?? sourceTweet.user.username,\n )}\n >\n @{sourceTweet.user.screenName ?? sourceTweet.user.username}\n </Link>\n )}\n </div>\n ),\n [hasSource, sourceTweet, t],\n );\n\n return (\n <TweetSource\n data={data}\n indicator={indicator}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React, { useMemo } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetRetweet({ data, headerActions, footerActions }: Props) {\n const { t } = useTranslation();\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n const indicator = useMemo(\n () => (\n <div className=\"flex items-center gap-2 text-sm\">\n <span>{t(\"mediaTrack.retweetedBy\")}</span>\n {hasSource && (\n <Link\n className=\"text-sm\"\n underline=\"hover\"\n target=\"_blank\"\n href={twitterUserUrl(\n sourceTweet.user.screenName ?? sourceTweet.user.username,\n )}\n >\n @{sourceTweet.user.screenName ?? sourceTweet.user.username}\n </Link>\n )}\n </div>\n ),\n [hasSource, sourceTweet, t],\n );\n\n return (\n <TweetSource\n data={data}\n indicator={indicator}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React from \"react\";\nimport { Skeleton } from \"@liberfi.io/ui\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetOriginal } from \"./tweet-original\";\nimport { TweetQuote } from \"./tweet-quote\";\nimport { TweetReply } from \"./tweet-reply\";\nimport { TweetRetweet } from \"./tweet-retweet\";\n\ntype Props = {\n data?: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n embed?: boolean;\n children?: React.ReactNode;\n loading?: boolean;\n};\n\n// ------------------------------------------------------------\nexport function TweetItem({\n data,\n headerActions,\n footerActions,\n embed = false,\n children,\n loading = false,\n}: Props) {\n if (loading || !data) {\n return <TweetSkeleton embed={embed} />;\n }\n\n const tweetType = data.tweet.type;\n\n // Render appropriate component based on tweet type\n const renderTweetComponent = () => {\n const commonProps = {\n data,\n headerActions,\n footerActions,\n embed,\n children,\n };\n\n switch (tweetType) {\n case \"reply\":\n return <TweetReply {...commonProps} />;\n case \"retweet\":\n return <TweetRetweet {...commonProps} />;\n case \"quote\":\n return <TweetQuote {...commonProps} />;\n default: // \"original\"\n return <TweetOriginal {...commonProps} />;\n }\n };\n\n return <div className=\"w-full\">{renderTweetComponent()}</div>;\n}\n\n// ------------------------------------------------------------\nfunction TweetSkeleton({ embed = false }: { embed?: boolean }) {\n const containerClass = embed\n ? \"bg-default-50 rounded-lg p-3 w-full mx-auto\"\n : \"bg-default-100 rounded-lg p-3 w-full mx-auto\";\n\n return (\n <div className={[\"flex flex-col gap-2\", containerClass].join(\" \")}>\n {/* User Info Skeleton */}\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"w-10 h-10 rounded-full\" />\n <div className=\"flex flex-col gap-1 flex-1\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-3 w-16\" />\n </div>\n <Skeleton className=\"h-3 w-12\" />\n </div>\n\n {/* Content Skeleton */}\n <div className=\"flex flex-col gap-2\">\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n\n {/* Media Skeleton */}\n <Skeleton className=\"h-48 w-full rounded-lg\" />\n\n {/* Actions Skeleton */}\n <div className=\"flex justify-between items-center pt-2\">\n <div className=\"flex gap-4\">\n <Skeleton className=\"h-6 w-16\" />\n <Skeleton className=\"h-6 w-16\" />\n <Skeleton className=\"h-6 w-16\" />\n </div>\n <Skeleton className=\"h-6 w-20\" />\n </div>\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { Avatar, Badge, Button, Image } from \"@liberfi.io/ui\";\nimport { formatPercent, SafeBigNumber } from \"@liberfi.io/utils\";\nimport { MediaToken } from \"../../../../types\";\n\ntype Props = {\n token: MediaToken;\n};\n\nexport function TweetTokenButton({ token }: Props) {\n const color = new SafeBigNumber(token.priceChange ?? \"0\").isPositive()\n ? \"primary\"\n : \"danger\";\n\n return (\n <Button\n color={color}\n variant=\"flat\"\n size=\"sm\"\n radius=\"full\"\n startContent={<TweetTokenIcon token={token} />}\n >\n <span>{token.symbol}</span>\n <span>\n {token.priceChange\n ? formatPercent(Number(token.priceChange) / 100)\n : \"--\"}\n </span>\n </Button>\n );\n}\n\nexport function TweetTokenIcon({ token }: Props) {\n const ChainIcon = useMemo(() => {\n return (\n <Image className=\"w-full h-full\" src={token.image} alt={token.chain} />\n );\n }, [token.chain, token.image]);\n\n return (\n <Badge\n className=\"w-2.5 h-2.5 p-0 border\"\n size=\"sm\"\n content={ChainIcon}\n shape=\"circle\"\n placement=\"bottom-right\"\n >\n <Avatar className=\"w-5 h-5\" radius=\"full\" src={token.image} />\n </Badge>\n );\n}\n","import { useCallback } from \"react\";\nimport { TweetMedia } from \"../../types\";\nimport { TweetTokenButton } from \"./tweet/tools/tweet-token-button\";\n// import { TweetTradeButton } from \"./tweet/tools/tweet-trade-button\";\nimport { TweetItem } from \"./tweet/tweet-item\";\n\ntype TweetsProps = {\n data: Array<TweetMedia>;\n loading: boolean;\n setIsPaused: (paused: boolean) => void;\n customHeaderActions?: (item: TweetMedia) => React.ReactNode;\n customFooterActions?: (item: TweetMedia) => React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function Tweets({\n data,\n loading,\n setIsPaused,\n customHeaderActions,\n customFooterActions,\n}: TweetsProps) {\n const footerActions = useCallback(\n (item: TweetMedia) => (\n <div className=\"flex gap-2.5 justify-between\">\n {item.token && <TweetTokenButton token={item.token} />}\n {customFooterActions?.(item)}\n {/* {item.token && <TweetTradeButton token={item.token} />} */}\n </div>\n ),\n [customFooterActions],\n );\n\n return (\n <div\n className=\"flex flex-col gap-2.5\"\n onMouseEnter={() => setIsPaused(true)}\n onMouseLeave={() => setIsPaused(false)}\n >\n {data.map((item: TweetMedia) => (\n <TweetItem\n key={item.id}\n data={item}\n headerActions={customHeaderActions?.(item)}\n footerActions={footerActions(item)}\n loading={loading}\n />\n ))}\n </div>\n );\n}\n","import { Skeleton } from \"@liberfi.io/ui\";\n\n// ------------------------------------------------------------\nexport function TweetSkeleton() {\n return (\n <div className=\"flex flex-col gap-2 bg-default-100 rounded-lg p-3 w-full mx-auto\">\n {/* User Info Skeleton */}\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"w-10 h-10 rounded-full\" />\n <div className=\"flex flex-col gap-1 flex-1\">\n <Skeleton className=\"h-4 w-40 rounded-md\" />\n <Skeleton className=\"h-3 w-32 rounded-md\" />\n </div>\n </div>\n\n {/* Content Skeleton */}\n <div className=\"flex flex-col gap-2\">\n <Skeleton className=\"h-4 w-full rounded-md\" />\n <Skeleton className=\"h-4 w-3/4 rounded-md\" />\n <Skeleton className=\"h-4 w-1/2 rounded-md\" />\n </div>\n\n {/* Media Skeleton */}\n <Skeleton className=\"h-48 w-full rounded-lg\" />\n </div>\n );\n}\n\nexport function TweetSkeletonList({ count = 3 }: { count: number }) {\n return (\n <div className=\"flex flex-col gap-2\">\n {Array.from({ length: count }).map((_, index) => (\n <TweetSkeleton key={index} />\n ))}\n </div>\n );\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { useMediaTrackRuntime } from \"../../hooks/useMediaTrackRuntime\";\nimport { TweetMedia } from \"../../types\";\n\nexport const useTweets = () => {\n const [medias, setMedias] = useState<Array<TweetMedia>>([]);\n const [loading, setLoading] = useState(true);\n const [isPaused, setIsPaused] = useState(false);\n\n const runtime = useMediaTrackRuntime();\n\n const handleMedia = useCallback(\n (media: TweetMedia) => {\n setMedias((prevMedias) => {\n const idx = prevMedias.findIndex((it) => it.id === media.id);\n let newMedias: Array<TweetMedia>;\n\n if (idx >= 0) {\n newMedias = prevMedias.map((item, index) =>\n index === idx ? media : item,\n );\n } else {\n if (isPaused) {\n return prevMedias;\n }\n newMedias = [media, ...prevMedias];\n }\n\n return newMedias.slice(0, 30);\n });\n setLoading(false);\n },\n [isPaused],\n );\n\n useEffect(() => {\n const subTweet = runtime.subscribe(\"x-monitor-basic\", handleMedia);\n const subTweetToken = runtime.subscribe(\"x-monitor-token\", handleMedia);\n return () => {\n subTweet.unsubscribe();\n subTweetToken.unsubscribe();\n };\n }, [runtime, handleMedia]);\n\n return { medias, loading, isPaused, setIsPaused };\n};\n","import { useEffect } from \"react\";\nimport { TweetMedia } from \"../../types\";\nimport { TweetSkeletonList } from \"./tweet/tweet-skeleton\";\nimport { useTweets } from \"./tweets.script\";\nimport { Tweets } from \"./tweets.ui\";\n\n// ------------------------------------------------------------\nexport type TweetsWidgetProps = {\n onPauseChange?: (paused: boolean) => void;\n customHeaderActions?: (item: TweetMedia) => React.ReactNode;\n customFooterActions?: (item: TweetMedia) => React.ReactNode;\n};\n\nexport function TweetsWidget({\n onPauseChange,\n customHeaderActions,\n customFooterActions,\n}: TweetsWidgetProps) {\n const { medias, loading, isPaused, setIsPaused } = useTweets();\n\n useEffect(() => {\n onPauseChange?.(isPaused);\n }, [isPaused, onPauseChange]);\n\n if (loading) {\n return <TweetSkeletonList count={3} />;\n }\n\n return (\n <Tweets\n data={medias}\n loading={loading}\n setIsPaused={setIsPaused}\n customHeaderActions={customHeaderActions}\n customFooterActions={customFooterActions}\n />\n );\n}\n","export type MediaTrackUnsubscribe = () => void;\n\nexport interface MediaTrackSubscription {\n unsubscribe: MediaTrackUnsubscribe;\n}\n\nexport interface MediaTrackRuntime<T = unknown> {\n readonly generation: number;\n connect(): void;\n disconnect(): void;\n setLocaleTransform(transform: ((payload: T) => T) | null): void;\n subscribe(channel: string, listener: (payload: T) => void): MediaTrackSubscription;\n publish(channel: string, payload: T): void;\n}\n\nexport function createMediaTrackRuntime<T = unknown>(): MediaTrackRuntime<T> {\n let generation = 0;\n let connected = false;\n let localeTransform: ((payload: T) => T) | null = null;\n const listeners = new Map<string, Set<(payload: T) => void>>();\n\n return {\n get generation() {\n return generation;\n },\n connect() {\n generation += 1;\n connected = true;\n },\n disconnect() {\n connected = false;\n },\n setLocaleTransform(transform) {\n localeTransform = transform;\n },\n subscribe(channel, listener) {\n let bucket = listeners.get(channel);\n if (!bucket) {\n bucket = new Set();\n listeners.set(channel, bucket);\n }\n bucket.add(listener);\n let unsubscribed = false;\n return {\n unsubscribe() {\n if (unsubscribed) return;\n unsubscribed = true;\n const current = listeners.get(channel);\n current?.delete(listener);\n if (current && current.size === 0) {\n listeners.delete(channel);\n }\n },\n };\n },\n publish(channel, payload) {\n if (!connected) return;\n const next = localeTransform ? localeTransform(payload) : payload;\n listeners.get(channel)?.forEach((listener) => listener(next));\n },\n };\n}\n","import { PropsWithChildren, useContext, useEffect, useMemo } from \"react\";\nimport { MediaTrackContext } from \"../context\";\nimport { MediaTrackRuntimeContext } from \"../context/MediaTrackRuntimeContext\";\nimport { createMediaTrackRuntime } from \"../runtime/media-track-runtime\";\nimport type { IMediaTrackClient, TweetMedia } from \"../types\";\n\nexport type MediaTrackProviderProps = PropsWithChildren<{\n client: IMediaTrackClient;\n}>;\n\nexport function MediaTrackProvider({\n client,\n children,\n}: MediaTrackProviderProps) {\n const runtime = useMemo(() => createMediaTrackRuntime<TweetMedia>(), []);\n\n return (\n <MediaTrackContext.Provider value={{ client }}>\n <MediaTrackRuntimeContext.Provider value={runtime}>\n <MediaTrackClientBridge client={client} />\n {children}\n </MediaTrackRuntimeContext.Provider>\n </MediaTrackContext.Provider>\n );\n}\n\nfunction MediaTrackClientBridge({ client }: { client: IMediaTrackClient }) {\n const runtime = useContext(MediaTrackRuntimeContext);\n useEffect(() => {\n if (!runtime) return;\n runtime.connect();\n const basic = client.subscribeTweetMedia({\n callback: (media) => runtime.publish(\"x-monitor-basic\", media),\n });\n const token = client.subscribeTweetMediaToken({\n callback: (media) => runtime.publish(\"x-monitor-token\", media),\n });\n return () => {\n basic.unsubscribe();\n token.unsubscribe();\n runtime.disconnect();\n };\n }, [client, runtime]);\n return null;\n}\n"]}
1
+ {"version":3,"sources":["../src/components/tweets/tweet/media/media-image.tsx","../src/components/tweets/tweet/media/media-video.tsx","../src/components/tweets/tweet/media/medias.tsx","../src/components/tweets/tweet/user/user-avatar.tsx","../src/components/tweets/tweet/user/user-info.tsx","../src/context/MediaTrackContext.ts","../src/context/MediaTrackRuntimeContext.ts","../src/hooks/useMediaTrackContext.ts","../src/hooks/useMediaTrackClient.ts","../src/hooks/useGenerateTweetMediaMemeMutation.ts","../src/hooks/useMediaTrackRuntime.ts","../src/hooks/useTranslateTweetMediaQuery.ts","../src/utils/parseText.tsx","../src/components/tweets/tweet/tools/translate.tsx","../src/components/tweets/tweet/tools/text-expand.tsx","../src/components/tweets/tweet/content/index.tsx","../src/components/tweets/tweet/tweet-source.tsx","../src/components/tweets/tweet/tweet-original.tsx","../src/components/tweets/tweet/tweet-quote.tsx","../src/components/tweets/tweet/tweet-reply.tsx","../src/components/tweets/tweet/tweet-retweet.tsx","../src/components/tweets/tweet/tweet-item.tsx","../src/components/tweets/tweet/tools/tweet-token-button.tsx","../src/components/tweets/tweets.ui.tsx","../src/components/tweets/tweet/tweet-skeleton.tsx","../src/components/tweets/tweets.script.ts","../src/components/tweets/tweets.widget.tsx","../src/runtime/media-track-runtime.ts","../src/providers/MediaTrackProvider.tsx"],"names":["MediaImage","src","isLoaded","setTrue","useBoolean","jsx","Skeleton","MediaVideo","Medias","medias","tweetHref","images","media","videos","renderVideos","video","renderImages","image","Link","jsxs","UserAvatar","url","name","size","fallbackName","useMemo","Avatar","UserInfo","user","renderTimestamp","renderActions","twitterUserUrl","MediaTrackContext","createContext","MediaTrackRuntimeContext","useMediaTrackContext","context","useContext","useMediaTrackClient","client","useGenerateTweetMediaMemeMutation","options","useMutation","params","useMediaTrackRuntime","runtime","translateTweetMedia","targetLanguage","useTranslateTweetMediaMutation","parseText","text","urlRegex","hashtagRegex","symbolRegex","matches","match","matchIndex","a","b","parts","lastIndex","key","item","e","hashtagUrl","Translate","data","embed","isTranslate","toggle","t","i18n","useTranslation","isTranslating","translatedText","setTranslatedText","useState","handleTranslate","useCallback","parsedText","Fragment","TranslateIcon","cn","TextExpand","isExpanded","onToggleExpand","renderExpand","ChevronUpIcon","ChevronDownIcon","Content","content","onLoad","ref","useRef","parsedContent","useEffect","current","TweetSource","headerActions","footerActions","indicator","children","formatAge","useLocalizedTimeFormatter","setIsExpanded","containerClass","tweet","age","useTickAge","twitterTweetUrl","TweetOriginal","TweetQuote","hasSource","TweetReply","sourceTweet","TweetRetweet","TweetItem","loading","TweetSkeleton","tweetType","commonProps","TweetTokenButton","token","color","SafeBigNumber","Button","TweetTokenIcon","formatPercent","ChainIcon","Image","Badge","Tweets","setIsPaused","customHeaderActions","customFooterActions","TweetSkeletonList","count","_","index","useTweets","setMedias","setLoading","isPaused","handleMedia","prevMedias","idx","it","newMedias","subTweet","subTweetToken","TweetsWidget","onPauseChange","createMediaTrackRuntime","generation","connected","localeTransform","listeners","transform","channel","listener","bucket","unsubscribed","payload","next","MediaTrackProvider","active","MediaTrackClientBridge","basic"],"mappings":"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","file":"index.js","sourcesContent":["import { useBoolean } from \"@liberfi.io/hooks\";\nimport { Skeleton } from \"@liberfi.io/ui\";\n\ntype Props = {\n src: string;\n};\n\n// ------------------------------------------------------------\nexport function MediaImage({ src }: Props) {\n const [isLoaded, { setTrue }] = useBoolean(false);\n if (!src) return null;\n\n return (\n <Skeleton isLoaded={isLoaded} className=\"w-full h-auto\">\n <img\n src={src}\n className=\"w-full h-full object-cover aspect-video\"\n onLoad={() => {\n setTrue();\n }}\n />\n </Skeleton>\n );\n}\n","type Props = {\n src: string;\n};\n\n// ------------------------------------------------------------\nexport function MediaVideo({ src }: Props) {\n if (!src) return null;\n\n return (\n <div className=\"w-full h-full overflow-hidden rounded-md mt-2\">\n <iframe\n className=\"w-full h-full aspect-video\"\n src={src}\n allowFullScreen\n />\n </div>\n );\n}\n","import { Link } from \"@liberfi.io/ui\";\nimport { TweetContentMedia } from \"../../../../types\";\nimport { MediaImage } from \"./media-image\";\nimport { MediaVideo } from \"./media-video\";\n\ntype Props = {\n medias: Array<TweetContentMedia>;\n tweetHref: string;\n};\n\nexport function Medias({ medias, tweetHref }: Props) {\n const images = medias.filter((media) => media.type === \"image\");\n const videos = medias.filter((media) => media.type === \"video\");\n\n const renderVideos = () => {\n if (!videos.length) return null;\n return (\n <div className={`grid grid-cols-1 gap-[1px] overflow-hidden rounded-md`}>\n {videos.map((video) => (\n <MediaVideo key={video.url} src={video.url} />\n ))}\n </div>\n );\n };\n\n const renderImages = () => {\n if (!images.length) return null;\n return (\n <div className={`grid grid-cols-1 gap-[1px] overflow-hidden rounded-md`}>\n {images.map((image) => (\n <Link key={image.url} href={tweetHref} target=\"_blank\">\n <MediaImage src={image.url} />\n </Link>\n ))}\n </div>\n );\n };\n\n return (\n <div className=\"flex flex-col gap-2\">\n {renderVideos()}\n {renderImages()}\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { Avatar, Skeleton } from \"@liberfi.io/ui\";\n\ntype Props = {\n url?: string;\n name?: string;\n size?: number;\n};\n\nexport function UserAvatar({ url, name = \"\", size = 36 }: Props) {\n const fallbackName = useMemo(() => (name ? name.slice(0, 2) : \"N/A\"), [name]);\n\n return (\n <Skeleton\n className=\"flex rounded-full flex-shrink-0\"\n style={{ width: size, height: size }}\n isLoaded={!!url}\n >\n <Avatar\n size=\"md\"\n color=\"primary\"\n radius=\"full\"\n showFallback\n name={fallbackName}\n src={url}\n style={{ width: size, height: size }}\n />\n </Skeleton>\n );\n}\n","import React from \"react\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetUser } from \"../../../../types\";\nimport { UserAvatar } from \"./user-avatar\";\n\ntype Props = {\n user: TweetUser;\n renderTimestamp?: React.ReactNode;\n renderActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function UserInfo({ user, renderTimestamp, renderActions }: Props) {\n return (\n <div className=\"flex items-center justify-between gap-1\">\n <div className=\"flex items-center gap-1\">\n <UserAvatar url={user.avatar} name={user.username} />\n <div className=\"flex flex-col gap-0.5\">\n <div className=\"flex flex-row items-baseline gap-1\">\n <span className=\"text-foreground font-semibold truncate leading-none\">\n {user.username}\n </span>\n {renderTimestamp}\n </div>\n <Link\n target=\"_blank\"\n underline=\"hover\"\n className=\"text-text-muted text-sm leading-none\"\n href={twitterUserUrl(user.screenName ?? user.username)}\n >\n @{user.screenName ?? user.username}\n </Link>\n </div>\n </div>\n {renderActions}\n </div>\n );\n}\n","import { createContext } from \"react\";\nimport { IMediaTrackClient } from \"../types\";\n\nexport interface MediaTrackContextValue {\n client: IMediaTrackClient;\n}\n\nexport const MediaTrackContext = createContext<MediaTrackContextValue>(\n {} as MediaTrackContextValue,\n);\n","import { createContext } from \"react\";\nimport type { TweetMedia } from \"../types\";\nimport type { MediaTrackRuntime } from \"../runtime/media-track-runtime\";\n\nexport const MediaTrackRuntimeContext =\n createContext<MediaTrackRuntime<TweetMedia> | null>(null);\n","import { useContext } from \"react\";\nimport { MediaTrackContext } from \"../context\";\n\nexport function useMediaTrackContext() {\n const context = useContext(MediaTrackContext);\n if (!context) {\n throw new Error(\n \"useMediaTrackContext must be used within a MediaTrackProvider\",\n );\n }\n return context;\n}\n","import { useMediaTrackContext } from \"./useMediaTrackContext\";\n\nexport function useMediaTrackClient() {\n const { client } = useMediaTrackContext();\n return client;\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport { GeneratedMemeInfo, TweetMedia } from \"../types\";\nimport { useMediaTrackClient } from \"./useMediaTrackClient\";\n\nexport function useGenerateTweetMediaMemeMutation(\n options: Omit<\n UseMutationOptions<GeneratedMemeInfo, Error, TweetMedia, string[]>,\n \"mutationFn\"\n > = {},\n) {\n const client = useMediaTrackClient();\n return useMutation({\n mutationFn: async (params: TweetMedia) => client.generateMeme(params),\n ...options,\n });\n}\n","import { useContext } from \"react\";\nimport { MediaTrackRuntimeContext } from \"../context/MediaTrackRuntimeContext\";\n\nexport function useMediaTrackRuntime() {\n const runtime = useContext(MediaTrackRuntimeContext);\n if (!runtime) {\n throw new Error(\n \"useMediaTrackRuntime must be used within a MediaTrackProvider\",\n );\n }\n return runtime;\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport { LocaleCode } from \"@liberfi.io/i18n\";\nimport { IMediaTrackClient, TweetMedia } from \"../types\";\nimport { useMediaTrackClient } from \"./useMediaTrackClient\";\n\nexport interface UseTranslateTweetMediaParams {\n media: TweetMedia;\n targetLanguage: LocaleCode;\n options?: {\n sourceLanguage?: LocaleCode;\n sourceTweet?: boolean;\n };\n}\n\nexport async function translateTweetMedia(\n client: IMediaTrackClient,\n { media, targetLanguage, options }: UseTranslateTweetMediaParams,\n) {\n return await client.translate(media, targetLanguage, options);\n}\n\nexport function useTranslateTweetMediaMutation(\n options: Omit<\n UseMutationOptions<string, Error, UseTranslateTweetMediaParams>,\n \"mutationFn\"\n > = {},\n) {\n const client = useMediaTrackClient();\n return useMutation({\n mutationFn: async (params: UseTranslateTweetMediaParams) =>\n translateTweetMedia(client, params),\n ...options,\n });\n}\n","interface MatchItem {\n index: number;\n length: number;\n text: string;\n type: \"url\" | \"hashtag\" | \"symbol\";\n}\n\nexport function parseText(text: string): (string | React.ReactElement)[] {\n const urlRegex = /(https?:\\/\\/[^\\s]+|www\\.[^\\s]+)/gi;\n const hashtagRegex = /#[\\w]+/g;\n const symbolRegex = /\\$[A-Za-z][A-Za-z0-9_]*/g;\n\n const matches: MatchItem[] = [];\n let match: RegExpExecArray | null;\n\n while ((match = urlRegex.exec(text)) !== null) {\n matches.push({\n index: match.index,\n length: match[0].length,\n text: match[0],\n type: \"url\",\n });\n }\n\n while ((match = hashtagRegex.exec(text)) !== null) {\n const matchIndex = match.index;\n const overlaps = matches.some(\n (m) => matchIndex >= m.index && matchIndex < m.index + m.length,\n );\n if (!overlaps) {\n matches.push({\n index: matchIndex,\n length: match[0].length,\n text: match[0],\n type: \"hashtag\",\n });\n }\n }\n\n while ((match = symbolRegex.exec(text)) !== null) {\n const matchIndex = match.index;\n const overlaps = matches.some(\n (m) => matchIndex >= m.index && matchIndex < m.index + m.length,\n );\n if (!overlaps) {\n matches.push({\n index: matchIndex,\n length: match[0].length,\n text: match[0],\n type: \"symbol\",\n });\n }\n }\n\n matches.sort((a, b) => a.index - b.index);\n\n const parts: (string | React.ReactElement)[] = [];\n let lastIndex = 0;\n let key = 0;\n\n matches.forEach((item) => {\n if (item.index > lastIndex) {\n parts.push(text.slice(lastIndex, item.index));\n }\n\n if (item.type === \"url\") {\n const url = item.text.startsWith(\"http\")\n ? item.text\n : `https://${item.text}`;\n parts.push(\n <a\n key={key++}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n onClick={(e) => e.stopPropagation()}\n >\n {item.text}\n </a>,\n );\n } else if (item.type === \"hashtag\") {\n const hashtag = item.text.slice(1); // 移除 #\n const hashtagUrl = `https://x.com/hashtag/${hashtag}`;\n parts.push(\n <a\n key={key++}\n href={hashtagUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n onClick={(e) => e.stopPropagation()}\n >\n {item.text}\n </a>,\n );\n } else if (item.type === \"symbol\") {\n parts.push(\n <span key={key++} className=\"text-primary\">\n {item.text}\n </span>,\n );\n }\n\n lastIndex = item.index + item.length;\n });\n\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n\n return parts.length > 0 ? parts : [text];\n}\n","import React, { MouseEvent, useCallback, useState } from \"react\";\nimport { useBoolean } from \"@liberfi.io/hooks\";\nimport { LocaleCode, useTranslation } from \"@liberfi.io/i18n\";\nimport { cn, Skeleton, TranslateIcon } from \"@liberfi.io/ui\";\nimport { useTranslateTweetMediaMutation } from \"../../../../hooks\";\nimport { TweetMedia } from \"../../../../types\";\nimport { parseText } from \"../../../../utils\";\n\ntype Props = {\n data: TweetMedia;\n embed?: boolean;\n text: string;\n renderActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function Translate({ data, embed, renderActions }: Props) {\n const [isTranslate, { toggle }] = useBoolean(false);\n\n const { t, i18n } = useTranslation();\n\n const { mutateAsync: translateTweetMedia, isPending: isTranslating } =\n useTranslateTweetMediaMutation();\n\n const [translatedText, setTranslatedText] = useState<\n (string | React.ReactElement)[] | null\n >(null);\n\n const handleTranslate = useCallback(\n async (e: MouseEvent<HTMLDivElement>) => {\n e.stopPropagation();\n toggle();\n if (!translatedText) {\n const text = await translateTweetMedia({\n media: data,\n targetLanguage: i18n.language as LocaleCode,\n options: {\n sourceTweet: embed,\n },\n });\n const parsedText = parseText(text);\n setTranslatedText(parsedText);\n }\n },\n [toggle, translateTweetMedia, data, i18n.language, translatedText, embed],\n );\n\n return (\n <>\n <div className=\"flex items-center gap-1 text-xs\">\n <div\n onClick={handleTranslate}\n className=\"flex items-center gap-0.5 cursor-pointer text-primary hover:text-foreground\"\n >\n <TranslateIcon width=\"14\" height=\"14\" />\n {isTranslate\n ? t(\"mediaTrack.tweets.translate.hide\")\n : t(\"mediaTrack.tweets.translate.show\")}\n </div>\n {renderActions}\n </div>\n <div\n className={cn(!isTranslate && \"hidden\")}\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n {isTranslate && (\n <div className=\"bg-content2 rounded-md p-2 text-text-primary text-sm leading-5\">\n {translatedText}\n {isTranslating && <Skeleton className=\"w-full h-4 rounded-md\" />}\n </div>\n )}\n </div>\n </>\n );\n}\n","import { useTranslation } from \"@liberfi.io/i18n\";\nimport { ChevronDownIcon, ChevronUpIcon } from \"@liberfi.io/ui\";\n\ntype Props = {\n isExpanded?: boolean;\n onToggleExpand?: (expanded: boolean) => void;\n};\n\nexport function TextExpand({ isExpanded, onToggleExpand }: Props) {\n const { t } = useTranslation();\n const renderExpand = () => {\n if (isExpanded) {\n return (\n <>\n <ChevronUpIcon\n className=\"border border-current\"\n width=\"12\"\n height=\"12\"\n />\n &nbsp;{t(\"mediaTrack.tweets.collapse\")}\n </>\n );\n }\n\n return (\n <>\n <ChevronDownIcon\n className=\"border border-current\"\n width=\"12\"\n height=\"12\"\n />\n &nbsp;{t(\"mediaTrack.tweets.expand\")}\n </>\n );\n };\n\n if (isExpanded === undefined) return null;\n\n return (\n <div className=\"flex items-center gap-1\">\n <div className=\"w-px h-2.5 bg-line-300\" />\n <button\n onClick={(e) => {\n e.stopPropagation();\n onToggleExpand?.(!isExpanded);\n }}\n className=\"flex items-center text-text-muted hover:text-foreground text-xs\"\n >\n {renderExpand()}\n </button>\n </div>\n );\n}\n","import { useEffect, useMemo, useRef } from \"react\";\nimport { parseText } from \"../../../../utils\";\n\ntype Props = {\n content: string;\n isExpanded?: boolean;\n onLoad?: () => void;\n};\n\n// ------------------------------------------------------------\nexport function Content({ content, isExpanded = false, onLoad }: Props) {\n const ref = useRef<HTMLDivElement>(null);\n\n const parsedContent = useMemo(() => parseText(content), [content]);\n\n useEffect(() => {\n const current = ref.current;\n if (!onLoad || !current) return;\n if (current.scrollHeight > current.clientHeight) {\n onLoad?.();\n }\n }, [isExpanded, onLoad]);\n\n return (\n <div\n ref={ref}\n className={[\n \"text-text-primary text-sm leading-5\",\n !isExpanded ? \"line-clamp-3\" : \"\",\n ].join(\" \")}\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n {parsedContent}\n </div>\n );\n}\n","import React, { useMemo, useState } from \"react\";\nimport { useTickAge } from \"@liberfi.io/hooks\";\nimport { useLocalizedTimeFormatter } from \"@liberfi.io/i18n\";\nimport { cn } from \"@liberfi.io/ui\";\nimport { twitterTweetUrl } from \"@liberfi.io/utils\";\nimport { Tweet, TweetMedia } from \"../../../types\";\nimport { Content } from \"./content\";\nimport { Medias } from \"./media\";\nimport { Translate, TextExpand } from \"./tools\";\nimport { UserInfo } from \"./user\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n embed?: boolean;\n indicator?: React.ReactNode;\n children?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetSource({\n data,\n headerActions,\n footerActions,\n embed = false,\n indicator,\n children,\n}: Props) {\n const { formatAge } = useLocalizedTimeFormatter();\n const [isExpanded, setIsExpanded] = useState<boolean | undefined>(undefined);\n\n const containerClass = useMemo(() => {\n return embed\n ? \"bg-default-50 rounded-lg p-3 w-full mx-auto\"\n : \"bg-default-100 hover:bg-default-200 rounded-lg p-3 w-full mx-auto\";\n }, [embed]);\n\n const tweet = useMemo(\n () => (embed ? data.sourceTweet! : data.tweet),\n [data, embed],\n );\n\n const age = useTickAge((tweet as Tweet).timestamp);\n\n return (\n <div\n className={cn(\"flex flex-col gap-1.5 cursor-pointer\", containerClass)}\n onClick={() => {\n window.open(twitterTweetUrl(tweet.tweetId), \"_blank\");\n }}\n >\n {/* -------- USER INFO -------- */}\n <UserInfo\n user={tweet.user}\n renderTimestamp={\n embed ? undefined : (\n <div className=\"text-xs text-primary\">{formatAge(age)}</div>\n )\n }\n renderActions={headerActions}\n />\n\n {/* -------- MESSAGE TYPE INDICATOR -------- */}\n {indicator}\n\n {/* -------- CONTENT -------- */}\n {tweet.content.text && (\n <Content\n content={tweet.content.text}\n isExpanded={isExpanded}\n onLoad={() => setIsExpanded(false)}\n />\n )}\n\n {/* -------- TOOLS -------- */}\n {tweet.content.text && (\n <Translate\n data={data}\n embed={embed}\n text={tweet.content.text}\n renderActions={\n <TextExpand\n isExpanded={isExpanded}\n onToggleExpand={setIsExpanded}\n />\n }\n />\n )}\n\n {/* -------- MEDIA -------- */}\n <div\n className={cn(\n (!tweet.content.medias || tweet.content.medias.length === 0) &&\n \"hidden\",\n )}\n >\n {tweet.content.medias && tweet.content.medias.length > 0 && (\n <Medias\n medias={tweet.content.medias}\n tweetHref={twitterTweetUrl(tweet.tweetId)}\n />\n )}\n </div>\n\n {/* -------- CHILDREN -------- */}\n {children}\n\n {/* -------- Custom ACTIONS -------- */}\n {footerActions}\n </div>\n );\n}\n","import React from \"react\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetOriginal({ data, headerActions, footerActions }: Props) {\n return (\n <TweetSource\n data={data}\n headerActions={headerActions}\n footerActions={footerActions}\n />\n );\n}\n","import React from \"react\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetQuote({ data, headerActions, footerActions }: Props) {\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n return (\n <TweetSource\n data={data}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React, { useMemo } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetReply({ data, headerActions, footerActions }: Props) {\n const { t } = useTranslation();\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n const indicator = useMemo(\n () => (\n <div className=\"flex items-center gap-2 text-sm\">\n <span>{t(\"mediaTrack.replyingTo\")}</span>\n {hasSource && (\n <Link\n className=\"text-sm\"\n underline=\"hover\"\n target=\"_blank\"\n href={twitterUserUrl(\n sourceTweet.user.screenName ?? sourceTweet.user.username,\n )}\n >\n @{sourceTweet.user.screenName ?? sourceTweet.user.username}\n </Link>\n )}\n </div>\n ),\n [hasSource, sourceTweet, t],\n );\n\n return (\n <TweetSource\n data={data}\n indicator={indicator}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React, { useMemo } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetRetweet({ data, headerActions, footerActions }: Props) {\n const { t } = useTranslation();\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n const indicator = useMemo(\n () => (\n <div className=\"flex items-center gap-2 text-sm\">\n <span>{t(\"mediaTrack.retweetedBy\")}</span>\n {hasSource && (\n <Link\n className=\"text-sm\"\n underline=\"hover\"\n target=\"_blank\"\n href={twitterUserUrl(\n sourceTweet.user.screenName ?? sourceTweet.user.username,\n )}\n >\n @{sourceTweet.user.screenName ?? sourceTweet.user.username}\n </Link>\n )}\n </div>\n ),\n [hasSource, sourceTweet, t],\n );\n\n return (\n <TweetSource\n data={data}\n indicator={indicator}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React from \"react\";\nimport { Skeleton } from \"@liberfi.io/ui\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetOriginal } from \"./tweet-original\";\nimport { TweetQuote } from \"./tweet-quote\";\nimport { TweetReply } from \"./tweet-reply\";\nimport { TweetRetweet } from \"./tweet-retweet\";\n\ntype Props = {\n data?: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n embed?: boolean;\n children?: React.ReactNode;\n loading?: boolean;\n};\n\n// ------------------------------------------------------------\nexport function TweetItem({\n data,\n headerActions,\n footerActions,\n embed = false,\n children,\n loading = false,\n}: Props) {\n if (loading || !data) {\n return <TweetSkeleton embed={embed} />;\n }\n\n const tweetType = data.tweet.type;\n\n // Render appropriate component based on tweet type\n const renderTweetComponent = () => {\n const commonProps = {\n data,\n headerActions,\n footerActions,\n embed,\n children,\n };\n\n switch (tweetType) {\n case \"reply\":\n return <TweetReply {...commonProps} />;\n case \"retweet\":\n return <TweetRetweet {...commonProps} />;\n case \"quote\":\n return <TweetQuote {...commonProps} />;\n default: // \"original\"\n return <TweetOriginal {...commonProps} />;\n }\n };\n\n return <div className=\"w-full\">{renderTweetComponent()}</div>;\n}\n\n// ------------------------------------------------------------\nfunction TweetSkeleton({ embed = false }: { embed?: boolean }) {\n const containerClass = embed\n ? \"bg-default-50 rounded-lg p-3 w-full mx-auto\"\n : \"bg-default-100 rounded-lg p-3 w-full mx-auto\";\n\n return (\n <div className={[\"flex flex-col gap-2\", containerClass].join(\" \")}>\n {/* User Info Skeleton */}\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"w-10 h-10 rounded-full\" />\n <div className=\"flex flex-col gap-1 flex-1\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-3 w-16\" />\n </div>\n <Skeleton className=\"h-3 w-12\" />\n </div>\n\n {/* Content Skeleton */}\n <div className=\"flex flex-col gap-2\">\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n\n {/* Media Skeleton */}\n <Skeleton className=\"h-48 w-full rounded-lg\" />\n\n {/* Actions Skeleton */}\n <div className=\"flex justify-between items-center pt-2\">\n <div className=\"flex gap-4\">\n <Skeleton className=\"h-6 w-16\" />\n <Skeleton className=\"h-6 w-16\" />\n <Skeleton className=\"h-6 w-16\" />\n </div>\n <Skeleton className=\"h-6 w-20\" />\n </div>\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { Avatar, Badge, Button, Image } from \"@liberfi.io/ui\";\nimport { formatPercent, SafeBigNumber } from \"@liberfi.io/utils\";\nimport { MediaToken } from \"../../../../types\";\n\ntype Props = {\n token: MediaToken;\n};\n\nexport function TweetTokenButton({ token }: Props) {\n const color = new SafeBigNumber(token.priceChange ?? \"0\").isPositive()\n ? \"primary\"\n : \"danger\";\n\n return (\n <Button\n color={color}\n variant=\"flat\"\n size=\"sm\"\n radius=\"full\"\n startContent={<TweetTokenIcon token={token} />}\n >\n <span>{token.symbol}</span>\n <span>\n {token.priceChange\n ? formatPercent(Number(token.priceChange) / 100)\n : \"--\"}\n </span>\n </Button>\n );\n}\n\nexport function TweetTokenIcon({ token }: Props) {\n const ChainIcon = useMemo(() => {\n return (\n <Image className=\"w-full h-full\" src={token.image} alt={token.chain} />\n );\n }, [token.chain, token.image]);\n\n return (\n <Badge\n className=\"w-2.5 h-2.5 p-0 border\"\n size=\"sm\"\n content={ChainIcon}\n shape=\"circle\"\n placement=\"bottom-right\"\n >\n <Avatar className=\"w-5 h-5\" radius=\"full\" src={token.image} />\n </Badge>\n );\n}\n","import { useCallback } from \"react\";\nimport { TweetMedia } from \"../../types\";\nimport { TweetTokenButton } from \"./tweet/tools/tweet-token-button\";\n// import { TweetTradeButton } from \"./tweet/tools/tweet-trade-button\";\nimport { TweetItem } from \"./tweet/tweet-item\";\n\ntype TweetsProps = {\n data: Array<TweetMedia>;\n loading: boolean;\n setIsPaused: (paused: boolean) => void;\n customHeaderActions?: (item: TweetMedia) => React.ReactNode;\n customFooterActions?: (item: TweetMedia) => React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function Tweets({\n data,\n loading,\n setIsPaused,\n customHeaderActions,\n customFooterActions,\n}: TweetsProps) {\n const footerActions = useCallback(\n (item: TweetMedia) => (\n <div className=\"flex gap-2.5 justify-between\">\n {item.token && <TweetTokenButton token={item.token} />}\n {customFooterActions?.(item)}\n {/* {item.token && <TweetTradeButton token={item.token} />} */}\n </div>\n ),\n [customFooterActions],\n );\n\n return (\n <div\n className=\"flex flex-col gap-2.5\"\n onMouseEnter={() => setIsPaused(true)}\n onMouseLeave={() => setIsPaused(false)}\n >\n {data.map((item: TweetMedia) => (\n <TweetItem\n key={item.id}\n data={item}\n headerActions={customHeaderActions?.(item)}\n footerActions={footerActions(item)}\n loading={loading}\n />\n ))}\n </div>\n );\n}\n","import { Skeleton } from \"@liberfi.io/ui\";\n\n// ------------------------------------------------------------\nexport function TweetSkeleton() {\n return (\n <div className=\"flex flex-col gap-2 bg-default-100 rounded-lg p-3 w-full mx-auto\">\n {/* User Info Skeleton */}\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"w-10 h-10 rounded-full\" />\n <div className=\"flex flex-col gap-1 flex-1\">\n <Skeleton className=\"h-4 w-40 rounded-md\" />\n <Skeleton className=\"h-3 w-32 rounded-md\" />\n </div>\n </div>\n\n {/* Content Skeleton */}\n <div className=\"flex flex-col gap-2\">\n <Skeleton className=\"h-4 w-full rounded-md\" />\n <Skeleton className=\"h-4 w-3/4 rounded-md\" />\n <Skeleton className=\"h-4 w-1/2 rounded-md\" />\n </div>\n\n {/* Media Skeleton */}\n <Skeleton className=\"h-48 w-full rounded-lg\" />\n </div>\n );\n}\n\nexport function TweetSkeletonList({ count = 3 }: { count: number }) {\n return (\n <div className=\"flex flex-col gap-2\">\n {Array.from({ length: count }).map((_, index) => (\n <TweetSkeleton key={index} />\n ))}\n </div>\n );\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { useMediaTrackRuntime } from \"../../hooks/useMediaTrackRuntime\";\nimport { TweetMedia } from \"../../types\";\n\nexport const useTweets = () => {\n const [medias, setMedias] = useState<Array<TweetMedia>>([]);\n const [loading, setLoading] = useState(true);\n const [isPaused, setIsPaused] = useState(false);\n\n const runtime = useMediaTrackRuntime();\n\n const handleMedia = useCallback(\n (media: TweetMedia) => {\n setMedias((prevMedias) => {\n const idx = prevMedias.findIndex((it) => it.id === media.id);\n let newMedias: Array<TweetMedia>;\n\n if (idx >= 0) {\n newMedias = prevMedias.map((item, index) =>\n index === idx ? media : item,\n );\n } else {\n if (isPaused) {\n return prevMedias;\n }\n newMedias = [media, ...prevMedias];\n }\n\n return newMedias.slice(0, 30);\n });\n setLoading(false);\n },\n [isPaused],\n );\n\n useEffect(() => {\n const subTweet = runtime.subscribe(\"x-monitor-basic\", handleMedia);\n const subTweetToken = runtime.subscribe(\"x-monitor-token\", handleMedia);\n return () => {\n subTweet.unsubscribe();\n subTweetToken.unsubscribe();\n };\n }, [runtime, handleMedia]);\n\n return { medias, loading, isPaused, setIsPaused };\n};\n","import { useEffect } from \"react\";\nimport { TweetMedia } from \"../../types\";\nimport { TweetSkeletonList } from \"./tweet/tweet-skeleton\";\nimport { useTweets } from \"./tweets.script\";\nimport { Tweets } from \"./tweets.ui\";\n\n// ------------------------------------------------------------\nexport type TweetsWidgetProps = {\n onPauseChange?: (paused: boolean) => void;\n customHeaderActions?: (item: TweetMedia) => React.ReactNode;\n customFooterActions?: (item: TweetMedia) => React.ReactNode;\n};\n\nexport function TweetsWidget({\n onPauseChange,\n customHeaderActions,\n customFooterActions,\n}: TweetsWidgetProps) {\n const { medias, loading, isPaused, setIsPaused } = useTweets();\n\n useEffect(() => {\n onPauseChange?.(isPaused);\n }, [isPaused, onPauseChange]);\n\n if (loading) {\n return <TweetSkeletonList count={3} />;\n }\n\n return (\n <Tweets\n data={medias}\n loading={loading}\n setIsPaused={setIsPaused}\n customHeaderActions={customHeaderActions}\n customFooterActions={customFooterActions}\n />\n );\n}\n","export type MediaTrackUnsubscribe = () => void;\n\nexport interface MediaTrackSubscription {\n unsubscribe: MediaTrackUnsubscribe;\n}\n\nexport interface MediaTrackRuntime<T = unknown> {\n readonly generation: number;\n connect(): void;\n disconnect(): void;\n setLocaleTransform(transform: ((payload: T) => T) | null): void;\n subscribe(channel: string, listener: (payload: T) => void): MediaTrackSubscription;\n publish(channel: string, payload: T): void;\n}\n\nexport function createMediaTrackRuntime<T = unknown>(): MediaTrackRuntime<T> {\n let generation = 0;\n let connected = false;\n let localeTransform: ((payload: T) => T) | null = null;\n const listeners = new Map<string, Set<(payload: T) => void>>();\n\n return {\n get generation() {\n return generation;\n },\n connect() {\n generation += 1;\n connected = true;\n },\n disconnect() {\n connected = false;\n },\n setLocaleTransform(transform) {\n localeTransform = transform;\n },\n subscribe(channel, listener) {\n let bucket = listeners.get(channel);\n if (!bucket) {\n bucket = new Set();\n listeners.set(channel, bucket);\n }\n bucket.add(listener);\n let unsubscribed = false;\n return {\n unsubscribe() {\n if (unsubscribed) return;\n unsubscribed = true;\n const current = listeners.get(channel);\n current?.delete(listener);\n if (current && current.size === 0) {\n listeners.delete(channel);\n }\n },\n };\n },\n publish(channel, payload) {\n if (!connected) return;\n const next = localeTransform ? localeTransform(payload) : payload;\n listeners.get(channel)?.forEach((listener) => listener(next));\n },\n };\n}\n","import { PropsWithChildren, useContext, useEffect, useMemo } from \"react\";\nimport { MediaTrackContext } from \"../context\";\nimport { MediaTrackRuntimeContext } from \"../context/MediaTrackRuntimeContext\";\nimport { createMediaTrackRuntime } from \"../runtime/media-track-runtime\";\nimport type { IMediaTrackClient, TweetMedia } from \"../types\";\n\nexport type MediaTrackProviderProps = PropsWithChildren<{\n client: IMediaTrackClient;\n active?: boolean;\n}>;\n\nexport function MediaTrackProvider({\n client,\n children,\n active = true,\n}: MediaTrackProviderProps) {\n const runtime = useMemo(() => createMediaTrackRuntime<TweetMedia>(), []);\n\n return (\n <MediaTrackContext.Provider value={{ client }}>\n <MediaTrackRuntimeContext.Provider value={runtime}>\n <MediaTrackClientBridge client={client} active={active} />\n {children}\n </MediaTrackRuntimeContext.Provider>\n </MediaTrackContext.Provider>\n );\n}\n\nfunction MediaTrackClientBridge({\n client,\n active,\n}: {\n client: IMediaTrackClient;\n active: boolean;\n}) {\n const runtime = useContext(MediaTrackRuntimeContext);\n useEffect(() => {\n if (!runtime || !active) return;\n runtime.connect();\n const basic = client.subscribeTweetMedia({\n callback: (media) => runtime.publish(\"x-monitor-basic\", media),\n });\n const token = client.subscribeTweetMediaToken({\n callback: (media) => runtime.publish(\"x-monitor-token\", media),\n });\n return () => {\n basic.unsubscribe();\n token.unsubscribe();\n runtime.disconnect();\n client.disconnect();\n };\n }, [active, client, runtime]);\n return null;\n}\n"]}
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import {useBoolean,useTickAge}from'@liberfi.io/hooks';import {Skeleton,Avatar,Link,TranslateIcon,cn,ChevronUpIcon,ChevronDownIcon,Button,Image,Badge}from'@liberfi.io/ui';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {twitterUserUrl,twitterTweetUrl,SafeBigNumber,formatPercent}from'@liberfi.io/utils';import {createContext,useMemo,useContext,useState,useCallback,useEffect,useRef}from'react';import {useTranslation,useLocalizedTimeFormatter}from'@liberfi.io/i18n';import {useMutation}from'@tanstack/react-query';function S({src:e}){let[t,{setTrue:o}]=useBoolean(false);return e?jsx(Skeleton,{isLoaded:t,className:"w-full h-auto",children:jsx("img",{src:e,className:"w-full h-full object-cover aspect-video",onLoad:()=>{o();}})}):null}function L({src:e}){return e?jsx("div",{className:"w-full h-full overflow-hidden rounded-md mt-2",children:jsx("iframe",{className:"w-full h-full aspect-video",src:e,allowFullScreen:true})}):null}function E({medias:e,tweetHref:t}){let o=e.filter(a=>a.type==="image"),n=e.filter(a=>a.type==="video"),r=()=>n.length?jsx("div",{className:"grid grid-cols-1 gap-[1px] overflow-hidden rounded-md",children:n.map(a=>jsx(L,{src:a.url},a.url))}):null,i=()=>o.length?jsx("div",{className:"grid grid-cols-1 gap-[1px] overflow-hidden rounded-md",children:o.map(a=>jsx(Link,{href:t,target:"_blank",children:jsx(S,{src:a.url})},a.url))}):null;return jsxs("div",{className:"flex flex-col gap-2",children:[r(),i()]})}function U({url:e,name:t="",size:o=36}){let n=useMemo(()=>t?t.slice(0,2):"N/A",[t]);return jsx(Skeleton,{className:"flex rounded-full flex-shrink-0",style:{width:o,height:o},isLoaded:!!e,children:jsx(Avatar,{size:"md",color:"primary",radius:"full",showFallback:true,name:n,src:e,style:{width:o,height:o}})})}function B({user:e,renderTimestamp:t,renderActions:o}){return jsxs("div",{className:"flex items-center justify-between gap-1",children:[jsxs("div",{className:"flex items-center gap-1",children:[jsx(U,{url:e.avatar,name:e.username}),jsxs("div",{className:"flex flex-col gap-0.5",children:[jsxs("div",{className:"flex flex-row items-baseline gap-1",children:[jsx("span",{className:"text-foreground font-semibold truncate leading-none",children:e.username}),t]}),jsxs(Link,{target:"_blank",underline:"hover",className:"text-text-muted text-sm leading-none",href:twitterUserUrl(e.screenName??e.username),children:["@",e.screenName??e.username]})]})]}),o]})}var N=createContext({});var h=createContext(null);function O(){let e=useContext(N);if(!e)throw new Error("useMediaTrackContext must be used within a MediaTrackProvider");return e}function y(){let{client:e}=O();return e}function Ue(e={}){let t=y();return useMutation({mutationFn:async o=>t.generateMeme(o),...e})}function F(){let e=useContext(h);if(!e)throw new Error("useMediaTrackRuntime must be used within a MediaTrackProvider");return e}async function se(e,{media:t,targetLanguage:o,options:n}){return await e.translate(t,o,n)}function H(e={}){let t=y();return useMutation({mutationFn:async o=>se(t,o),...e})}function R(e){let t=/(https?:\/\/[^\s]+|www\.[^\s]+)/gi,o=/#[\w]+/g,n=/\$[A-Za-z][A-Za-z0-9_]*/g,r=[],i;for(;(i=t.exec(e))!==null;)r.push({index:i.index,length:i[0].length,text:i[0],type:"url"});for(;(i=o.exec(e))!==null;){let s=i.index;r.some(m=>s>=m.index&&s<m.index+m.length)||r.push({index:s,length:i[0].length,text:i[0],type:"hashtag"});}for(;(i=n.exec(e))!==null;){let s=i.index;r.some(m=>s>=m.index&&s<m.index+m.length)||r.push({index:s,length:i[0].length,text:i[0],type:"symbol"});}r.sort((s,c)=>s.index-c.index);let a=[],l=0,d=0;return r.forEach(s=>{if(s.index>l&&a.push(e.slice(l,s.index)),s.type==="url"){let c=s.text.startsWith("http")?s.text:`https://${s.text}`;a.push(jsx("a",{href:c,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",onClick:m=>m.stopPropagation(),children:s.text},d++));}else if(s.type==="hashtag"){let m=`https://x.com/hashtag/${s.text.slice(1)}`;a.push(jsx("a",{href:m,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",onClick:T=>T.stopPropagation(),children:s.text},d++));}else s.type==="symbol"&&a.push(jsx("span",{className:"text-primary",children:s.text},d++));l=s.index+s.length;}),l<e.length&&a.push(e.slice(l)),a.length>0?a:[e]}function W({data:e,embed:t,renderActions:o}){let[n,{toggle:r}]=useBoolean(false),{t:i,i18n:a}=useTranslation(),{mutateAsync:l,isPending:d}=H(),[s,c]=useState(null),m=useCallback(async T=>{if(T.stopPropagation(),r(),!s){let I=await l({media:e,targetLanguage:a.language,options:{sourceTweet:t}}),Me=R(I);c(Me);}},[r,l,e,a.language,s,t]);return jsxs(Fragment,{children:[jsxs("div",{className:"flex items-center gap-1 text-xs",children:[jsxs("div",{onClick:m,className:"flex items-center gap-0.5 cursor-pointer text-primary hover:text-foreground",children:[jsx(TranslateIcon,{width:"14",height:"14"}),i(n?"mediaTrack.tweets.translate.hide":"mediaTrack.tweets.translate.show")]}),o]}),jsx("div",{className:cn(!n&&"hidden"),onClick:T=>{T.stopPropagation();},children:n&&jsxs("div",{className:"bg-content2 rounded-md p-2 text-text-primary text-sm leading-5",children:[s,d&&jsx(Skeleton,{className:"w-full h-4 rounded-md"})]})})]})}function G({isExpanded:e,onToggleExpand:t}){let{t:o}=useTranslation(),n=()=>e?jsxs(Fragment,{children:[jsx(ChevronUpIcon,{className:"border border-current",width:"12",height:"12"}),"\xA0",o("mediaTrack.tweets.collapse")]}):jsxs(Fragment,{children:[jsx(ChevronDownIcon,{className:"border border-current",width:"12",height:"12"}),"\xA0",o("mediaTrack.tweets.expand")]});return e===void 0?null:jsxs("div",{className:"flex items-center gap-1",children:[jsx("div",{className:"w-px h-2.5 bg-line-300"}),jsx("button",{onClick:r=>{r.stopPropagation(),t?.(!e);},className:"flex items-center text-text-muted hover:text-foreground text-xs",children:n()})]})}function de({content:e,isExpanded:t=false,onLoad:o}){let n=useRef(null),r=useMemo(()=>R(e),[e]);return useEffect(()=>{let i=n.current;!o||!i||i.scrollHeight>i.clientHeight&&o?.();},[t,o]),jsx("div",{ref:n,className:["text-text-primary text-sm leading-5",t?"":"line-clamp-3"].join(" "),onClick:i=>{i.stopPropagation();},children:r})}function u({data:e,headerActions:t,footerActions:o,embed:n=false,indicator:r,children:i}){let{formatAge:a}=useLocalizedTimeFormatter(),[l,d]=useState(void 0),s=useMemo(()=>n?"bg-default-50 rounded-lg p-3 w-full mx-auto":"bg-default-100 hover:bg-default-200 rounded-lg p-3 w-full mx-auto",[n]),c=useMemo(()=>n?e.sourceTweet:e.tweet,[e,n]),m=useTickAge(c.timestamp);return jsxs("div",{className:cn("flex flex-col gap-1.5 cursor-pointer",s),onClick:()=>{window.open(twitterTweetUrl(c.tweetId),"_blank");},children:[jsx(B,{user:c.user,renderTimestamp:n?void 0:jsx("div",{className:"text-xs text-primary",children:a(m)}),renderActions:t}),r,c.content.text&&jsx(de,{content:c.content.text,isExpanded:l,onLoad:()=>d(false)}),c.content.text&&jsx(W,{data:e,embed:n,text:c.content.text,renderActions:jsx(G,{isExpanded:l,onToggleExpand:d})}),jsx("div",{className:cn((!c.content.medias||c.content.medias.length===0)&&"hidden"),children:c.content.medias&&c.content.medias.length>0&&jsx(E,{medias:c.content.medias,tweetHref:twitterTweetUrl(c.tweetId)})}),i,o]})}function D({data:e,headerActions:t,footerActions:o}){return jsx(u,{data:e,headerActions:t,footerActions:o})}function Q({data:e,headerActions:t,footerActions:o}){let r=!!e.sourceTweet;return jsx(u,{data:e,headerActions:t,footerActions:o,children:r?jsx(u,{data:e,embed:true}):null})}function Z({data:e,headerActions:t,footerActions:o}){let{t:n}=useTranslation(),r=e.sourceTweet,i=!!r,a=useMemo(()=>jsxs("div",{className:"flex items-center gap-2 text-sm",children:[jsx("span",{children:n("mediaTrack.replyingTo")}),i&&jsxs(Link,{className:"text-sm",underline:"hover",target:"_blank",href:twitterUserUrl(r.user.screenName??r.user.username),children:["@",r.user.screenName??r.user.username]})]}),[i,r,n]);return jsx(u,{data:e,indicator:a,headerActions:t,footerActions:o,children:i?jsx(u,{data:e,embed:true}):null})}function J({data:e,headerActions:t,footerActions:o}){let{t:n}=useTranslation(),r=e.sourceTweet,i=!!r,a=useMemo(()=>jsxs("div",{className:"flex items-center gap-2 text-sm",children:[jsx("span",{children:n("mediaTrack.retweetedBy")}),i&&jsxs(Link,{className:"text-sm",underline:"hover",target:"_blank",href:twitterUserUrl(r.user.screenName??r.user.username),children:["@",r.user.screenName??r.user.username]})]}),[i,r,n]);return jsx(u,{data:e,indicator:a,headerActions:t,footerActions:o,children:i?jsx(u,{data:e,embed:true}):null})}function K({data:e,headerActions:t,footerActions:o,embed:n=false,children:r,loading:i=false}){if(i||!e)return jsx(mt,{embed:n});let a=e.tweet.type;return jsx("div",{className:"w-full",children:(()=>{let d={data:e,headerActions:t,footerActions:o,embed:n,children:r};switch(a){case "reply":return jsx(Z,{...d});case "retweet":return jsx(J,{...d});case "quote":return jsx(Q,{...d});default:return jsx(D,{...d})}})()})}function mt({embed:e=false}){return jsxs("div",{className:["flex flex-col gap-2",e?"bg-default-50 rounded-lg p-3 w-full mx-auto":"bg-default-100 rounded-lg p-3 w-full mx-auto"].join(" "),children:[jsxs("div",{className:"flex items-center gap-3",children:[jsx(Skeleton,{className:"w-10 h-10 rounded-full"}),jsxs("div",{className:"flex flex-col gap-1 flex-1",children:[jsx(Skeleton,{className:"h-4 w-24"}),jsx(Skeleton,{className:"h-3 w-16"})]}),jsx(Skeleton,{className:"h-3 w-12"})]}),jsxs("div",{className:"flex flex-col gap-2",children:[jsx(Skeleton,{className:"h-4 w-full"}),jsx(Skeleton,{className:"h-4 w-3/4"}),jsx(Skeleton,{className:"h-4 w-1/2"})]}),jsx(Skeleton,{className:"h-48 w-full rounded-lg"}),jsxs("div",{className:"flex justify-between items-center pt-2",children:[jsxs("div",{className:"flex gap-4",children:[jsx(Skeleton,{className:"h-6 w-16"}),jsx(Skeleton,{className:"h-6 w-16"}),jsx(Skeleton,{className:"h-6 w-16"})]}),jsx(Skeleton,{className:"h-6 w-20"})]})]})}function xe({token:e}){let t=new SafeBigNumber(e.priceChange??"0").isPositive()?"primary":"danger";return jsxs(Button,{color:t,variant:"flat",size:"sm",radius:"full",startContent:jsx(ht,{token:e}),children:[jsx("span",{children:e.symbol}),jsx("span",{children:e.priceChange?formatPercent(Number(e.priceChange)/100):"--"})]})}function ht({token:e}){let t=useMemo(()=>jsx(Image,{className:"w-full h-full",src:e.image,alt:e.chain}),[e.chain,e.image]);return jsx(Badge,{className:"w-2.5 h-2.5 p-0 border",size:"sm",content:t,shape:"circle",placement:"bottom-right",children:jsx(Avatar,{className:"w-5 h-5",radius:"full",src:e.image})})}function Y({data:e,loading:t,setIsPaused:o,customHeaderActions:n,customFooterActions:r}){let i=useCallback(a=>jsxs("div",{className:"flex gap-2.5 justify-between",children:[a.token&&jsx(xe,{token:a.token}),r?.(a)]}),[r]);return jsx("div",{className:"flex flex-col gap-2.5",onMouseEnter:()=>o(true),onMouseLeave:()=>o(false),children:e.map(a=>jsx(K,{data:a,headerActions:n?.(a),footerActions:i(a),loading:t},a.id))})}function we(){return jsxs("div",{className:"flex flex-col gap-2 bg-default-100 rounded-lg p-3 w-full mx-auto",children:[jsxs("div",{className:"flex items-center gap-3",children:[jsx(Skeleton,{className:"w-10 h-10 rounded-full"}),jsxs("div",{className:"flex flex-col gap-1 flex-1",children:[jsx(Skeleton,{className:"h-4 w-40 rounded-md"}),jsx(Skeleton,{className:"h-3 w-32 rounded-md"})]})]}),jsxs("div",{className:"flex flex-col gap-2",children:[jsx(Skeleton,{className:"h-4 w-full rounded-md"}),jsx(Skeleton,{className:"h-4 w-3/4 rounded-md"}),jsx(Skeleton,{className:"h-4 w-1/2 rounded-md"})]}),jsx(Skeleton,{className:"h-48 w-full rounded-lg"})]})}function j({count:e=3}){return jsx("div",{className:"flex flex-col gap-2",children:Array.from({length:e}).map((t,o)=>jsx(we,{},o))})}var te=()=>{let[e,t]=useState([]),[o,n]=useState(true),[r,i]=useState(false),a=F(),l=useCallback(d=>{t(s=>{let c=s.findIndex(T=>T.id===d.id),m;if(c>=0)m=s.map((T,I)=>I===c?d:T);else {if(r)return s;m=[d,...s];}return m.slice(0,30)}),n(false);},[r]);return useEffect(()=>{let d=a.subscribe("x-monitor-basic",l),s=a.subscribe("x-monitor-token",l);return ()=>{d.unsubscribe(),s.unsubscribe();}},[a,l]),{medias:e,loading:o,isPaused:r,setIsPaused:i}};function Rt({onPauseChange:e,customHeaderActions:t,customFooterActions:o}){let{medias:n,loading:r,isPaused:i,setIsPaused:a}=te();return useEffect(()=>{e?.(i);},[i,e]),r?jsx(j,{count:3}):jsx(Y,{data:n,loading:r,setIsPaused:a,customHeaderActions:t,customFooterActions:o})}function re(){let e=0,t=false,o=null,n=new Map;return {get generation(){return e},connect(){e+=1,t=true;},disconnect(){t=false;},setLocaleTransform(r){o=r;},subscribe(r,i){let a=n.get(r);a||(a=new Set,n.set(r,a)),a.add(i);let l=false;return {unsubscribe(){if(l)return;l=true;let d=n.get(r);d?.delete(i),d&&d.size===0&&n.delete(r);}}},publish(r,i){if(!t)return;let a=o?o(i):i;n.get(r)?.forEach(l=>l(a));}}}function It({client:e,children:t}){let o=useMemo(()=>re(),[]);return jsx(N.Provider,{value:{client:e},children:jsxs(h.Provider,{value:o,children:[jsx(St,{client:e}),t]})})}function St({client:e}){let t=useContext(h);return useEffect(()=>{if(!t)return;t.connect();let o=e.subscribeTweetMedia({callback:r=>t.publish("x-monitor-basic",r)}),n=e.subscribeTweetMediaToken({callback:r=>t.publish("x-monitor-token",r)});return ()=>{o.unsubscribe(),n.unsubscribe(),t.disconnect();}},[e,t]),null}
1
+ import {useBoolean,useTickAge}from'@liberfi.io/hooks';import {Skeleton,Avatar,Link,TranslateIcon,cn,ChevronUpIcon,ChevronDownIcon,Button,Image,Badge}from'@liberfi.io/ui';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {twitterUserUrl,twitterTweetUrl,SafeBigNumber,formatPercent}from'@liberfi.io/utils';import {createContext,useMemo,useContext,useState,useCallback,useEffect,useRef}from'react';import {useTranslation,useLocalizedTimeFormatter}from'@liberfi.io/i18n';import {useMutation}from'@tanstack/react-query';function S({src:e}){let[r,{setTrue:t}]=useBoolean(false);return e?jsx(Skeleton,{isLoaded:r,className:"w-full h-auto",children:jsx("img",{src:e,className:"w-full h-full object-cover aspect-video",onLoad:()=>{t();}})}):null}function L({src:e}){return e?jsx("div",{className:"w-full h-full overflow-hidden rounded-md mt-2",children:jsx("iframe",{className:"w-full h-full aspect-video",src:e,allowFullScreen:true})}):null}function E({medias:e,tweetHref:r}){let t=e.filter(i=>i.type==="image"),n=e.filter(i=>i.type==="video"),o=()=>n.length?jsx("div",{className:"grid grid-cols-1 gap-[1px] overflow-hidden rounded-md",children:n.map(i=>jsx(L,{src:i.url},i.url))}):null,a=()=>t.length?jsx("div",{className:"grid grid-cols-1 gap-[1px] overflow-hidden rounded-md",children:t.map(i=>jsx(Link,{href:r,target:"_blank",children:jsx(S,{src:i.url})},i.url))}):null;return jsxs("div",{className:"flex flex-col gap-2",children:[o(),a()]})}function U({url:e,name:r="",size:t=36}){let n=useMemo(()=>r?r.slice(0,2):"N/A",[r]);return jsx(Skeleton,{className:"flex rounded-full flex-shrink-0",style:{width:t,height:t},isLoaded:!!e,children:jsx(Avatar,{size:"md",color:"primary",radius:"full",showFallback:true,name:n,src:e,style:{width:t,height:t}})})}function B({user:e,renderTimestamp:r,renderActions:t}){return jsxs("div",{className:"flex items-center justify-between gap-1",children:[jsxs("div",{className:"flex items-center gap-1",children:[jsx(U,{url:e.avatar,name:e.username}),jsxs("div",{className:"flex flex-col gap-0.5",children:[jsxs("div",{className:"flex flex-row items-baseline gap-1",children:[jsx("span",{className:"text-foreground font-semibold truncate leading-none",children:e.username}),r]}),jsxs(Link,{target:"_blank",underline:"hover",className:"text-text-muted text-sm leading-none",href:twitterUserUrl(e.screenName??e.username),children:["@",e.screenName??e.username]})]})]}),t]})}var N=createContext({});var h=createContext(null);function O(){let e=useContext(N);if(!e)throw new Error("useMediaTrackContext must be used within a MediaTrackProvider");return e}function y(){let{client:e}=O();return e}function Ue(e={}){let r=y();return useMutation({mutationFn:async t=>r.generateMeme(t),...e})}function F(){let e=useContext(h);if(!e)throw new Error("useMediaTrackRuntime must be used within a MediaTrackProvider");return e}async function se(e,{media:r,targetLanguage:t,options:n}){return await e.translate(r,t,n)}function H(e={}){let r=y();return useMutation({mutationFn:async t=>se(r,t),...e})}function R(e){let r=/(https?:\/\/[^\s]+|www\.[^\s]+)/gi,t=/#[\w]+/g,n=/\$[A-Za-z][A-Za-z0-9_]*/g,o=[],a;for(;(a=r.exec(e))!==null;)o.push({index:a.index,length:a[0].length,text:a[0],type:"url"});for(;(a=t.exec(e))!==null;){let s=a.index;o.some(m=>s>=m.index&&s<m.index+m.length)||o.push({index:s,length:a[0].length,text:a[0],type:"hashtag"});}for(;(a=n.exec(e))!==null;){let s=a.index;o.some(m=>s>=m.index&&s<m.index+m.length)||o.push({index:s,length:a[0].length,text:a[0],type:"symbol"});}o.sort((s,c)=>s.index-c.index);let i=[],l=0,d=0;return o.forEach(s=>{if(s.index>l&&i.push(e.slice(l,s.index)),s.type==="url"){let c=s.text.startsWith("http")?s.text:`https://${s.text}`;i.push(jsx("a",{href:c,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",onClick:m=>m.stopPropagation(),children:s.text},d++));}else if(s.type==="hashtag"){let m=`https://x.com/hashtag/${s.text.slice(1)}`;i.push(jsx("a",{href:m,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",onClick:T=>T.stopPropagation(),children:s.text},d++));}else s.type==="symbol"&&i.push(jsx("span",{className:"text-primary",children:s.text},d++));l=s.index+s.length;}),l<e.length&&i.push(e.slice(l)),i.length>0?i:[e]}function W({data:e,embed:r,renderActions:t}){let[n,{toggle:o}]=useBoolean(false),{t:a,i18n:i}=useTranslation(),{mutateAsync:l,isPending:d}=H(),[s,c]=useState(null),m=useCallback(async T=>{if(T.stopPropagation(),o(),!s){let I=await l({media:e,targetLanguage:i.language,options:{sourceTweet:r}}),Me=R(I);c(Me);}},[o,l,e,i.language,s,r]);return jsxs(Fragment,{children:[jsxs("div",{className:"flex items-center gap-1 text-xs",children:[jsxs("div",{onClick:m,className:"flex items-center gap-0.5 cursor-pointer text-primary hover:text-foreground",children:[jsx(TranslateIcon,{width:"14",height:"14"}),a(n?"mediaTrack.tweets.translate.hide":"mediaTrack.tweets.translate.show")]}),t]}),jsx("div",{className:cn(!n&&"hidden"),onClick:T=>{T.stopPropagation();},children:n&&jsxs("div",{className:"bg-content2 rounded-md p-2 text-text-primary text-sm leading-5",children:[s,d&&jsx(Skeleton,{className:"w-full h-4 rounded-md"})]})})]})}function G({isExpanded:e,onToggleExpand:r}){let{t}=useTranslation(),n=()=>e?jsxs(Fragment,{children:[jsx(ChevronUpIcon,{className:"border border-current",width:"12",height:"12"}),"\xA0",t("mediaTrack.tweets.collapse")]}):jsxs(Fragment,{children:[jsx(ChevronDownIcon,{className:"border border-current",width:"12",height:"12"}),"\xA0",t("mediaTrack.tweets.expand")]});return e===void 0?null:jsxs("div",{className:"flex items-center gap-1",children:[jsx("div",{className:"w-px h-2.5 bg-line-300"}),jsx("button",{onClick:o=>{o.stopPropagation(),r?.(!e);},className:"flex items-center text-text-muted hover:text-foreground text-xs",children:n()})]})}function de({content:e,isExpanded:r=false,onLoad:t}){let n=useRef(null),o=useMemo(()=>R(e),[e]);return useEffect(()=>{let a=n.current;!t||!a||a.scrollHeight>a.clientHeight&&t?.();},[r,t]),jsx("div",{ref:n,className:["text-text-primary text-sm leading-5",r?"":"line-clamp-3"].join(" "),onClick:a=>{a.stopPropagation();},children:o})}function u({data:e,headerActions:r,footerActions:t,embed:n=false,indicator:o,children:a}){let{formatAge:i}=useLocalizedTimeFormatter(),[l,d]=useState(void 0),s=useMemo(()=>n?"bg-default-50 rounded-lg p-3 w-full mx-auto":"bg-default-100 hover:bg-default-200 rounded-lg p-3 w-full mx-auto",[n]),c=useMemo(()=>n?e.sourceTweet:e.tweet,[e,n]),m=useTickAge(c.timestamp);return jsxs("div",{className:cn("flex flex-col gap-1.5 cursor-pointer",s),onClick:()=>{window.open(twitterTweetUrl(c.tweetId),"_blank");},children:[jsx(B,{user:c.user,renderTimestamp:n?void 0:jsx("div",{className:"text-xs text-primary",children:i(m)}),renderActions:r}),o,c.content.text&&jsx(de,{content:c.content.text,isExpanded:l,onLoad:()=>d(false)}),c.content.text&&jsx(W,{data:e,embed:n,text:c.content.text,renderActions:jsx(G,{isExpanded:l,onToggleExpand:d})}),jsx("div",{className:cn((!c.content.medias||c.content.medias.length===0)&&"hidden"),children:c.content.medias&&c.content.medias.length>0&&jsx(E,{medias:c.content.medias,tweetHref:twitterTweetUrl(c.tweetId)})}),a,t]})}function D({data:e,headerActions:r,footerActions:t}){return jsx(u,{data:e,headerActions:r,footerActions:t})}function Q({data:e,headerActions:r,footerActions:t}){let o=!!e.sourceTweet;return jsx(u,{data:e,headerActions:r,footerActions:t,children:o?jsx(u,{data:e,embed:true}):null})}function Z({data:e,headerActions:r,footerActions:t}){let{t:n}=useTranslation(),o=e.sourceTweet,a=!!o,i=useMemo(()=>jsxs("div",{className:"flex items-center gap-2 text-sm",children:[jsx("span",{children:n("mediaTrack.replyingTo")}),a&&jsxs(Link,{className:"text-sm",underline:"hover",target:"_blank",href:twitterUserUrl(o.user.screenName??o.user.username),children:["@",o.user.screenName??o.user.username]})]}),[a,o,n]);return jsx(u,{data:e,indicator:i,headerActions:r,footerActions:t,children:a?jsx(u,{data:e,embed:true}):null})}function J({data:e,headerActions:r,footerActions:t}){let{t:n}=useTranslation(),o=e.sourceTweet,a=!!o,i=useMemo(()=>jsxs("div",{className:"flex items-center gap-2 text-sm",children:[jsx("span",{children:n("mediaTrack.retweetedBy")}),a&&jsxs(Link,{className:"text-sm",underline:"hover",target:"_blank",href:twitterUserUrl(o.user.screenName??o.user.username),children:["@",o.user.screenName??o.user.username]})]}),[a,o,n]);return jsx(u,{data:e,indicator:i,headerActions:r,footerActions:t,children:a?jsx(u,{data:e,embed:true}):null})}function K({data:e,headerActions:r,footerActions:t,embed:n=false,children:o,loading:a=false}){if(a||!e)return jsx(mt,{embed:n});let i=e.tweet.type;return jsx("div",{className:"w-full",children:(()=>{let d={data:e,headerActions:r,footerActions:t,embed:n,children:o};switch(i){case "reply":return jsx(Z,{...d});case "retweet":return jsx(J,{...d});case "quote":return jsx(Q,{...d});default:return jsx(D,{...d})}})()})}function mt({embed:e=false}){return jsxs("div",{className:["flex flex-col gap-2",e?"bg-default-50 rounded-lg p-3 w-full mx-auto":"bg-default-100 rounded-lg p-3 w-full mx-auto"].join(" "),children:[jsxs("div",{className:"flex items-center gap-3",children:[jsx(Skeleton,{className:"w-10 h-10 rounded-full"}),jsxs("div",{className:"flex flex-col gap-1 flex-1",children:[jsx(Skeleton,{className:"h-4 w-24"}),jsx(Skeleton,{className:"h-3 w-16"})]}),jsx(Skeleton,{className:"h-3 w-12"})]}),jsxs("div",{className:"flex flex-col gap-2",children:[jsx(Skeleton,{className:"h-4 w-full"}),jsx(Skeleton,{className:"h-4 w-3/4"}),jsx(Skeleton,{className:"h-4 w-1/2"})]}),jsx(Skeleton,{className:"h-48 w-full rounded-lg"}),jsxs("div",{className:"flex justify-between items-center pt-2",children:[jsxs("div",{className:"flex gap-4",children:[jsx(Skeleton,{className:"h-6 w-16"}),jsx(Skeleton,{className:"h-6 w-16"}),jsx(Skeleton,{className:"h-6 w-16"})]}),jsx(Skeleton,{className:"h-6 w-20"})]})]})}function xe({token:e}){let r=new SafeBigNumber(e.priceChange??"0").isPositive()?"primary":"danger";return jsxs(Button,{color:r,variant:"flat",size:"sm",radius:"full",startContent:jsx(ht,{token:e}),children:[jsx("span",{children:e.symbol}),jsx("span",{children:e.priceChange?formatPercent(Number(e.priceChange)/100):"--"})]})}function ht({token:e}){let r=useMemo(()=>jsx(Image,{className:"w-full h-full",src:e.image,alt:e.chain}),[e.chain,e.image]);return jsx(Badge,{className:"w-2.5 h-2.5 p-0 border",size:"sm",content:r,shape:"circle",placement:"bottom-right",children:jsx(Avatar,{className:"w-5 h-5",radius:"full",src:e.image})})}function Y({data:e,loading:r,setIsPaused:t,customHeaderActions:n,customFooterActions:o}){let a=useCallback(i=>jsxs("div",{className:"flex gap-2.5 justify-between",children:[i.token&&jsx(xe,{token:i.token}),o?.(i)]}),[o]);return jsx("div",{className:"flex flex-col gap-2.5",onMouseEnter:()=>t(true),onMouseLeave:()=>t(false),children:e.map(i=>jsx(K,{data:i,headerActions:n?.(i),footerActions:a(i),loading:r},i.id))})}function we(){return jsxs("div",{className:"flex flex-col gap-2 bg-default-100 rounded-lg p-3 w-full mx-auto",children:[jsxs("div",{className:"flex items-center gap-3",children:[jsx(Skeleton,{className:"w-10 h-10 rounded-full"}),jsxs("div",{className:"flex flex-col gap-1 flex-1",children:[jsx(Skeleton,{className:"h-4 w-40 rounded-md"}),jsx(Skeleton,{className:"h-3 w-32 rounded-md"})]})]}),jsxs("div",{className:"flex flex-col gap-2",children:[jsx(Skeleton,{className:"h-4 w-full rounded-md"}),jsx(Skeleton,{className:"h-4 w-3/4 rounded-md"}),jsx(Skeleton,{className:"h-4 w-1/2 rounded-md"})]}),jsx(Skeleton,{className:"h-48 w-full rounded-lg"})]})}function j({count:e=3}){return jsx("div",{className:"flex flex-col gap-2",children:Array.from({length:e}).map((r,t)=>jsx(we,{},t))})}var te=()=>{let[e,r]=useState([]),[t,n]=useState(true),[o,a]=useState(false),i=F(),l=useCallback(d=>{r(s=>{let c=s.findIndex(T=>T.id===d.id),m;if(c>=0)m=s.map((T,I)=>I===c?d:T);else {if(o)return s;m=[d,...s];}return m.slice(0,30)}),n(false);},[o]);return useEffect(()=>{let d=i.subscribe("x-monitor-basic",l),s=i.subscribe("x-monitor-token",l);return ()=>{d.unsubscribe(),s.unsubscribe();}},[i,l]),{medias:e,loading:t,isPaused:o,setIsPaused:a}};function Rt({onPauseChange:e,customHeaderActions:r,customFooterActions:t}){let{medias:n,loading:o,isPaused:a,setIsPaused:i}=te();return useEffect(()=>{e?.(a);},[a,e]),o?jsx(j,{count:3}):jsx(Y,{data:n,loading:o,setIsPaused:i,customHeaderActions:r,customFooterActions:t})}function re(){let e=0,r=false,t=null,n=new Map;return {get generation(){return e},connect(){e+=1,r=true;},disconnect(){r=false;},setLocaleTransform(o){t=o;},subscribe(o,a){let i=n.get(o);i||(i=new Set,n.set(o,i)),i.add(a);let l=false;return {unsubscribe(){if(l)return;l=true;let d=n.get(o);d?.delete(a),d&&d.size===0&&n.delete(o);}}},publish(o,a){if(!r)return;let i=t?t(a):a;n.get(o)?.forEach(l=>l(i));}}}function It({client:e,children:r,active:t=true}){let n=useMemo(()=>re(),[]);return jsx(N.Provider,{value:{client:e},children:jsxs(h.Provider,{value:n,children:[jsx(St,{client:e,active:t}),r]})})}function St({client:e,active:r}){let t=useContext(h);return useEffect(()=>{if(!t||!r)return;t.connect();let n=e.subscribeTweetMedia({callback:a=>t.publish("x-monitor-basic",a)}),o=e.subscribeTweetMediaToken({callback:a=>t.publish("x-monitor-token",a)});return ()=>{n.unsubscribe(),o.unsubscribe(),t.disconnect(),e.disconnect();}},[r,e,t]),null}
2
2
  export{S as MediaImage,N as MediaTrackContext,It as MediaTrackProvider,h as MediaTrackRuntimeContext,L as MediaVideo,E as Medias,G as TextExpand,W as Translate,K as TweetItem,D as TweetOriginal,Q as TweetQuote,Z as TweetReply,J as TweetRetweet,we as TweetSkeleton,j as TweetSkeletonList,u as TweetSource,Y as Tweets,Rt as TweetsWidget,U as UserAvatar,B as UserInfo,re as createMediaTrackRuntime,se as translateTweetMedia,Ue as useGenerateTweetMediaMemeMutation,y as useMediaTrackClient,O as useMediaTrackContext,F as useMediaTrackRuntime,H as useTranslateTweetMediaMutation,te as useTweets};//# sourceMappingURL=index.mjs.map
3
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/tweets/tweet/media/media-image.tsx","../src/components/tweets/tweet/media/media-video.tsx","../src/components/tweets/tweet/media/medias.tsx","../src/components/tweets/tweet/user/user-avatar.tsx","../src/components/tweets/tweet/user/user-info.tsx","../src/context/MediaTrackContext.ts","../src/context/MediaTrackRuntimeContext.ts","../src/hooks/useMediaTrackContext.ts","../src/hooks/useMediaTrackClient.ts","../src/hooks/useGenerateTweetMediaMemeMutation.ts","../src/hooks/useMediaTrackRuntime.ts","../src/hooks/useTranslateTweetMediaQuery.ts","../src/utils/parseText.tsx","../src/components/tweets/tweet/tools/translate.tsx","../src/components/tweets/tweet/tools/text-expand.tsx","../src/components/tweets/tweet/content/index.tsx","../src/components/tweets/tweet/tweet-source.tsx","../src/components/tweets/tweet/tweet-original.tsx","../src/components/tweets/tweet/tweet-quote.tsx","../src/components/tweets/tweet/tweet-reply.tsx","../src/components/tweets/tweet/tweet-retweet.tsx","../src/components/tweets/tweet/tweet-item.tsx","../src/components/tweets/tweet/tools/tweet-token-button.tsx","../src/components/tweets/tweets.ui.tsx","../src/components/tweets/tweet/tweet-skeleton.tsx","../src/components/tweets/tweets.script.ts","../src/components/tweets/tweets.widget.tsx","../src/runtime/media-track-runtime.ts","../src/providers/MediaTrackProvider.tsx"],"names":["MediaImage","src","isLoaded","setTrue","useBoolean","jsx","Skeleton","MediaVideo","Medias","medias","tweetHref","images","media","videos","renderVideos","video","renderImages","image","Link","jsxs","UserAvatar","url","name","size","fallbackName","useMemo","Avatar","UserInfo","user","renderTimestamp","renderActions","twitterUserUrl","MediaTrackContext","createContext","MediaTrackRuntimeContext","useMediaTrackContext","context","useContext","useMediaTrackClient","client","useGenerateTweetMediaMemeMutation","options","useMutation","params","useMediaTrackRuntime","runtime","translateTweetMedia","targetLanguage","useTranslateTweetMediaMutation","parseText","text","urlRegex","hashtagRegex","symbolRegex","matches","match","matchIndex","a","b","parts","lastIndex","key","item","e","hashtagUrl","Translate","data","embed","isTranslate","toggle","t","i18n","useTranslation","isTranslating","translatedText","setTranslatedText","useState","handleTranslate","useCallback","parsedText","Fragment","TranslateIcon","cn","TextExpand","isExpanded","onToggleExpand","renderExpand","ChevronUpIcon","ChevronDownIcon","Content","content","onLoad","ref","useRef","parsedContent","useEffect","current","TweetSource","headerActions","footerActions","indicator","children","formatAge","useLocalizedTimeFormatter","setIsExpanded","containerClass","tweet","age","useTickAge","twitterTweetUrl","TweetOriginal","TweetQuote","hasSource","TweetReply","sourceTweet","TweetRetweet","TweetItem","loading","TweetSkeleton","tweetType","commonProps","TweetTokenButton","token","color","SafeBigNumber","Button","TweetTokenIcon","formatPercent","ChainIcon","Image","Badge","Tweets","setIsPaused","customHeaderActions","customFooterActions","TweetSkeletonList","count","_","index","useTweets","setMedias","setLoading","isPaused","handleMedia","prevMedias","idx","it","newMedias","subTweet","subTweetToken","TweetsWidget","onPauseChange","createMediaTrackRuntime","generation","connected","localeTransform","listeners","transform","channel","listener","bucket","unsubscribed","payload","next","MediaTrackProvider","MediaTrackClientBridge","basic"],"mappings":"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","file":"index.mjs","sourcesContent":["import { useBoolean } from \"@liberfi.io/hooks\";\nimport { Skeleton } from \"@liberfi.io/ui\";\n\ntype Props = {\n src: string;\n};\n\n// ------------------------------------------------------------\nexport function MediaImage({ src }: Props) {\n const [isLoaded, { setTrue }] = useBoolean(false);\n if (!src) return null;\n\n return (\n <Skeleton isLoaded={isLoaded} className=\"w-full h-auto\">\n <img\n src={src}\n className=\"w-full h-full object-cover aspect-video\"\n onLoad={() => {\n setTrue();\n }}\n />\n </Skeleton>\n );\n}\n","type Props = {\n src: string;\n};\n\n// ------------------------------------------------------------\nexport function MediaVideo({ src }: Props) {\n if (!src) return null;\n\n return (\n <div className=\"w-full h-full overflow-hidden rounded-md mt-2\">\n <iframe\n className=\"w-full h-full aspect-video\"\n src={src}\n allowFullScreen\n />\n </div>\n );\n}\n","import { Link } from \"@liberfi.io/ui\";\nimport { TweetContentMedia } from \"../../../../types\";\nimport { MediaImage } from \"./media-image\";\nimport { MediaVideo } from \"./media-video\";\n\ntype Props = {\n medias: Array<TweetContentMedia>;\n tweetHref: string;\n};\n\nexport function Medias({ medias, tweetHref }: Props) {\n const images = medias.filter((media) => media.type === \"image\");\n const videos = medias.filter((media) => media.type === \"video\");\n\n const renderVideos = () => {\n if (!videos.length) return null;\n return (\n <div className={`grid grid-cols-1 gap-[1px] overflow-hidden rounded-md`}>\n {videos.map((video) => (\n <MediaVideo key={video.url} src={video.url} />\n ))}\n </div>\n );\n };\n\n const renderImages = () => {\n if (!images.length) return null;\n return (\n <div className={`grid grid-cols-1 gap-[1px] overflow-hidden rounded-md`}>\n {images.map((image) => (\n <Link key={image.url} href={tweetHref} target=\"_blank\">\n <MediaImage src={image.url} />\n </Link>\n ))}\n </div>\n );\n };\n\n return (\n <div className=\"flex flex-col gap-2\">\n {renderVideos()}\n {renderImages()}\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { Avatar, Skeleton } from \"@liberfi.io/ui\";\n\ntype Props = {\n url?: string;\n name?: string;\n size?: number;\n};\n\nexport function UserAvatar({ url, name = \"\", size = 36 }: Props) {\n const fallbackName = useMemo(() => (name ? name.slice(0, 2) : \"N/A\"), [name]);\n\n return (\n <Skeleton\n className=\"flex rounded-full flex-shrink-0\"\n style={{ width: size, height: size }}\n isLoaded={!!url}\n >\n <Avatar\n size=\"md\"\n color=\"primary\"\n radius=\"full\"\n showFallback\n name={fallbackName}\n src={url}\n style={{ width: size, height: size }}\n />\n </Skeleton>\n );\n}\n","import React from \"react\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetUser } from \"../../../../types\";\nimport { UserAvatar } from \"./user-avatar\";\n\ntype Props = {\n user: TweetUser;\n renderTimestamp?: React.ReactNode;\n renderActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function UserInfo({ user, renderTimestamp, renderActions }: Props) {\n return (\n <div className=\"flex items-center justify-between gap-1\">\n <div className=\"flex items-center gap-1\">\n <UserAvatar url={user.avatar} name={user.username} />\n <div className=\"flex flex-col gap-0.5\">\n <div className=\"flex flex-row items-baseline gap-1\">\n <span className=\"text-foreground font-semibold truncate leading-none\">\n {user.username}\n </span>\n {renderTimestamp}\n </div>\n <Link\n target=\"_blank\"\n underline=\"hover\"\n className=\"text-text-muted text-sm leading-none\"\n href={twitterUserUrl(user.screenName ?? user.username)}\n >\n @{user.screenName ?? user.username}\n </Link>\n </div>\n </div>\n {renderActions}\n </div>\n );\n}\n","import { createContext } from \"react\";\nimport { IMediaTrackClient } from \"../types\";\n\nexport interface MediaTrackContextValue {\n client: IMediaTrackClient;\n}\n\nexport const MediaTrackContext = createContext<MediaTrackContextValue>(\n {} as MediaTrackContextValue,\n);\n","import { createContext } from \"react\";\nimport type { TweetMedia } from \"../types\";\nimport type { MediaTrackRuntime } from \"../runtime/media-track-runtime\";\n\nexport const MediaTrackRuntimeContext =\n createContext<MediaTrackRuntime<TweetMedia> | null>(null);\n","import { useContext } from \"react\";\nimport { MediaTrackContext } from \"../context\";\n\nexport function useMediaTrackContext() {\n const context = useContext(MediaTrackContext);\n if (!context) {\n throw new Error(\n \"useMediaTrackContext must be used within a MediaTrackProvider\",\n );\n }\n return context;\n}\n","import { useMediaTrackContext } from \"./useMediaTrackContext\";\n\nexport function useMediaTrackClient() {\n const { client } = useMediaTrackContext();\n return client;\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport { GeneratedMemeInfo, TweetMedia } from \"../types\";\nimport { useMediaTrackClient } from \"./useMediaTrackClient\";\n\nexport function useGenerateTweetMediaMemeMutation(\n options: Omit<\n UseMutationOptions<GeneratedMemeInfo, Error, TweetMedia, string[]>,\n \"mutationFn\"\n > = {},\n) {\n const client = useMediaTrackClient();\n return useMutation({\n mutationFn: async (params: TweetMedia) => client.generateMeme(params),\n ...options,\n });\n}\n","import { useContext } from \"react\";\nimport { MediaTrackRuntimeContext } from \"../context/MediaTrackRuntimeContext\";\n\nexport function useMediaTrackRuntime() {\n const runtime = useContext(MediaTrackRuntimeContext);\n if (!runtime) {\n throw new Error(\n \"useMediaTrackRuntime must be used within a MediaTrackProvider\",\n );\n }\n return runtime;\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport { LocaleCode } from \"@liberfi.io/i18n\";\nimport { IMediaTrackClient, TweetMedia } from \"../types\";\nimport { useMediaTrackClient } from \"./useMediaTrackClient\";\n\nexport interface UseTranslateTweetMediaParams {\n media: TweetMedia;\n targetLanguage: LocaleCode;\n options?: {\n sourceLanguage?: LocaleCode;\n sourceTweet?: boolean;\n };\n}\n\nexport async function translateTweetMedia(\n client: IMediaTrackClient,\n { media, targetLanguage, options }: UseTranslateTweetMediaParams,\n) {\n return await client.translate(media, targetLanguage, options);\n}\n\nexport function useTranslateTweetMediaMutation(\n options: Omit<\n UseMutationOptions<string, Error, UseTranslateTweetMediaParams>,\n \"mutationFn\"\n > = {},\n) {\n const client = useMediaTrackClient();\n return useMutation({\n mutationFn: async (params: UseTranslateTweetMediaParams) =>\n translateTweetMedia(client, params),\n ...options,\n });\n}\n","interface MatchItem {\n index: number;\n length: number;\n text: string;\n type: \"url\" | \"hashtag\" | \"symbol\";\n}\n\nexport function parseText(text: string): (string | React.ReactElement)[] {\n const urlRegex = /(https?:\\/\\/[^\\s]+|www\\.[^\\s]+)/gi;\n const hashtagRegex = /#[\\w]+/g;\n const symbolRegex = /\\$[A-Za-z][A-Za-z0-9_]*/g;\n\n const matches: MatchItem[] = [];\n let match: RegExpExecArray | null;\n\n while ((match = urlRegex.exec(text)) !== null) {\n matches.push({\n index: match.index,\n length: match[0].length,\n text: match[0],\n type: \"url\",\n });\n }\n\n while ((match = hashtagRegex.exec(text)) !== null) {\n const matchIndex = match.index;\n const overlaps = matches.some(\n (m) => matchIndex >= m.index && matchIndex < m.index + m.length,\n );\n if (!overlaps) {\n matches.push({\n index: matchIndex,\n length: match[0].length,\n text: match[0],\n type: \"hashtag\",\n });\n }\n }\n\n while ((match = symbolRegex.exec(text)) !== null) {\n const matchIndex = match.index;\n const overlaps = matches.some(\n (m) => matchIndex >= m.index && matchIndex < m.index + m.length,\n );\n if (!overlaps) {\n matches.push({\n index: matchIndex,\n length: match[0].length,\n text: match[0],\n type: \"symbol\",\n });\n }\n }\n\n matches.sort((a, b) => a.index - b.index);\n\n const parts: (string | React.ReactElement)[] = [];\n let lastIndex = 0;\n let key = 0;\n\n matches.forEach((item) => {\n if (item.index > lastIndex) {\n parts.push(text.slice(lastIndex, item.index));\n }\n\n if (item.type === \"url\") {\n const url = item.text.startsWith(\"http\")\n ? item.text\n : `https://${item.text}`;\n parts.push(\n <a\n key={key++}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n onClick={(e) => e.stopPropagation()}\n >\n {item.text}\n </a>,\n );\n } else if (item.type === \"hashtag\") {\n const hashtag = item.text.slice(1); // 移除 #\n const hashtagUrl = `https://x.com/hashtag/${hashtag}`;\n parts.push(\n <a\n key={key++}\n href={hashtagUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n onClick={(e) => e.stopPropagation()}\n >\n {item.text}\n </a>,\n );\n } else if (item.type === \"symbol\") {\n parts.push(\n <span key={key++} className=\"text-primary\">\n {item.text}\n </span>,\n );\n }\n\n lastIndex = item.index + item.length;\n });\n\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n\n return parts.length > 0 ? parts : [text];\n}\n","import React, { MouseEvent, useCallback, useState } from \"react\";\nimport { useBoolean } from \"@liberfi.io/hooks\";\nimport { LocaleCode, useTranslation } from \"@liberfi.io/i18n\";\nimport { cn, Skeleton, TranslateIcon } from \"@liberfi.io/ui\";\nimport { useTranslateTweetMediaMutation } from \"../../../../hooks\";\nimport { TweetMedia } from \"../../../../types\";\nimport { parseText } from \"../../../../utils\";\n\ntype Props = {\n data: TweetMedia;\n embed?: boolean;\n text: string;\n renderActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function Translate({ data, embed, renderActions }: Props) {\n const [isTranslate, { toggle }] = useBoolean(false);\n\n const { t, i18n } = useTranslation();\n\n const { mutateAsync: translateTweetMedia, isPending: isTranslating } =\n useTranslateTweetMediaMutation();\n\n const [translatedText, setTranslatedText] = useState<\n (string | React.ReactElement)[] | null\n >(null);\n\n const handleTranslate = useCallback(\n async (e: MouseEvent<HTMLDivElement>) => {\n e.stopPropagation();\n toggle();\n if (!translatedText) {\n const text = await translateTweetMedia({\n media: data,\n targetLanguage: i18n.language as LocaleCode,\n options: {\n sourceTweet: embed,\n },\n });\n const parsedText = parseText(text);\n setTranslatedText(parsedText);\n }\n },\n [toggle, translateTweetMedia, data, i18n.language, translatedText, embed],\n );\n\n return (\n <>\n <div className=\"flex items-center gap-1 text-xs\">\n <div\n onClick={handleTranslate}\n className=\"flex items-center gap-0.5 cursor-pointer text-primary hover:text-foreground\"\n >\n <TranslateIcon width=\"14\" height=\"14\" />\n {isTranslate\n ? t(\"mediaTrack.tweets.translate.hide\")\n : t(\"mediaTrack.tweets.translate.show\")}\n </div>\n {renderActions}\n </div>\n <div\n className={cn(!isTranslate && \"hidden\")}\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n {isTranslate && (\n <div className=\"bg-content2 rounded-md p-2 text-text-primary text-sm leading-5\">\n {translatedText}\n {isTranslating && <Skeleton className=\"w-full h-4 rounded-md\" />}\n </div>\n )}\n </div>\n </>\n );\n}\n","import { useTranslation } from \"@liberfi.io/i18n\";\nimport { ChevronDownIcon, ChevronUpIcon } from \"@liberfi.io/ui\";\n\ntype Props = {\n isExpanded?: boolean;\n onToggleExpand?: (expanded: boolean) => void;\n};\n\nexport function TextExpand({ isExpanded, onToggleExpand }: Props) {\n const { t } = useTranslation();\n const renderExpand = () => {\n if (isExpanded) {\n return (\n <>\n <ChevronUpIcon\n className=\"border border-current\"\n width=\"12\"\n height=\"12\"\n />\n &nbsp;{t(\"mediaTrack.tweets.collapse\")}\n </>\n );\n }\n\n return (\n <>\n <ChevronDownIcon\n className=\"border border-current\"\n width=\"12\"\n height=\"12\"\n />\n &nbsp;{t(\"mediaTrack.tweets.expand\")}\n </>\n );\n };\n\n if (isExpanded === undefined) return null;\n\n return (\n <div className=\"flex items-center gap-1\">\n <div className=\"w-px h-2.5 bg-line-300\" />\n <button\n onClick={(e) => {\n e.stopPropagation();\n onToggleExpand?.(!isExpanded);\n }}\n className=\"flex items-center text-text-muted hover:text-foreground text-xs\"\n >\n {renderExpand()}\n </button>\n </div>\n );\n}\n","import { useEffect, useMemo, useRef } from \"react\";\nimport { parseText } from \"../../../../utils\";\n\ntype Props = {\n content: string;\n isExpanded?: boolean;\n onLoad?: () => void;\n};\n\n// ------------------------------------------------------------\nexport function Content({ content, isExpanded = false, onLoad }: Props) {\n const ref = useRef<HTMLDivElement>(null);\n\n const parsedContent = useMemo(() => parseText(content), [content]);\n\n useEffect(() => {\n const current = ref.current;\n if (!onLoad || !current) return;\n if (current.scrollHeight > current.clientHeight) {\n onLoad?.();\n }\n }, [isExpanded, onLoad]);\n\n return (\n <div\n ref={ref}\n className={[\n \"text-text-primary text-sm leading-5\",\n !isExpanded ? \"line-clamp-3\" : \"\",\n ].join(\" \")}\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n {parsedContent}\n </div>\n );\n}\n","import React, { useMemo, useState } from \"react\";\nimport { useTickAge } from \"@liberfi.io/hooks\";\nimport { useLocalizedTimeFormatter } from \"@liberfi.io/i18n\";\nimport { cn } from \"@liberfi.io/ui\";\nimport { twitterTweetUrl } from \"@liberfi.io/utils\";\nimport { Tweet, TweetMedia } from \"../../../types\";\nimport { Content } from \"./content\";\nimport { Medias } from \"./media\";\nimport { Translate, TextExpand } from \"./tools\";\nimport { UserInfo } from \"./user\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n embed?: boolean;\n indicator?: React.ReactNode;\n children?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetSource({\n data,\n headerActions,\n footerActions,\n embed = false,\n indicator,\n children,\n}: Props) {\n const { formatAge } = useLocalizedTimeFormatter();\n const [isExpanded, setIsExpanded] = useState<boolean | undefined>(undefined);\n\n const containerClass = useMemo(() => {\n return embed\n ? \"bg-default-50 rounded-lg p-3 w-full mx-auto\"\n : \"bg-default-100 hover:bg-default-200 rounded-lg p-3 w-full mx-auto\";\n }, [embed]);\n\n const tweet = useMemo(\n () => (embed ? data.sourceTweet! : data.tweet),\n [data, embed],\n );\n\n const age = useTickAge((tweet as Tweet).timestamp);\n\n return (\n <div\n className={cn(\"flex flex-col gap-1.5 cursor-pointer\", containerClass)}\n onClick={() => {\n window.open(twitterTweetUrl(tweet.tweetId), \"_blank\");\n }}\n >\n {/* -------- USER INFO -------- */}\n <UserInfo\n user={tweet.user}\n renderTimestamp={\n embed ? undefined : (\n <div className=\"text-xs text-primary\">{formatAge(age)}</div>\n )\n }\n renderActions={headerActions}\n />\n\n {/* -------- MESSAGE TYPE INDICATOR -------- */}\n {indicator}\n\n {/* -------- CONTENT -------- */}\n {tweet.content.text && (\n <Content\n content={tweet.content.text}\n isExpanded={isExpanded}\n onLoad={() => setIsExpanded(false)}\n />\n )}\n\n {/* -------- TOOLS -------- */}\n {tweet.content.text && (\n <Translate\n data={data}\n embed={embed}\n text={tweet.content.text}\n renderActions={\n <TextExpand\n isExpanded={isExpanded}\n onToggleExpand={setIsExpanded}\n />\n }\n />\n )}\n\n {/* -------- MEDIA -------- */}\n <div\n className={cn(\n (!tweet.content.medias || tweet.content.medias.length === 0) &&\n \"hidden\",\n )}\n >\n {tweet.content.medias && tweet.content.medias.length > 0 && (\n <Medias\n medias={tweet.content.medias}\n tweetHref={twitterTweetUrl(tweet.tweetId)}\n />\n )}\n </div>\n\n {/* -------- CHILDREN -------- */}\n {children}\n\n {/* -------- Custom ACTIONS -------- */}\n {footerActions}\n </div>\n );\n}\n","import React from \"react\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetOriginal({ data, headerActions, footerActions }: Props) {\n return (\n <TweetSource\n data={data}\n headerActions={headerActions}\n footerActions={footerActions}\n />\n );\n}\n","import React from \"react\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetQuote({ data, headerActions, footerActions }: Props) {\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n return (\n <TweetSource\n data={data}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React, { useMemo } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetReply({ data, headerActions, footerActions }: Props) {\n const { t } = useTranslation();\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n const indicator = useMemo(\n () => (\n <div className=\"flex items-center gap-2 text-sm\">\n <span>{t(\"mediaTrack.replyingTo\")}</span>\n {hasSource && (\n <Link\n className=\"text-sm\"\n underline=\"hover\"\n target=\"_blank\"\n href={twitterUserUrl(\n sourceTweet.user.screenName ?? sourceTweet.user.username,\n )}\n >\n @{sourceTweet.user.screenName ?? sourceTweet.user.username}\n </Link>\n )}\n </div>\n ),\n [hasSource, sourceTweet, t],\n );\n\n return (\n <TweetSource\n data={data}\n indicator={indicator}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React, { useMemo } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetRetweet({ data, headerActions, footerActions }: Props) {\n const { t } = useTranslation();\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n const indicator = useMemo(\n () => (\n <div className=\"flex items-center gap-2 text-sm\">\n <span>{t(\"mediaTrack.retweetedBy\")}</span>\n {hasSource && (\n <Link\n className=\"text-sm\"\n underline=\"hover\"\n target=\"_blank\"\n href={twitterUserUrl(\n sourceTweet.user.screenName ?? sourceTweet.user.username,\n )}\n >\n @{sourceTweet.user.screenName ?? sourceTweet.user.username}\n </Link>\n )}\n </div>\n ),\n [hasSource, sourceTweet, t],\n );\n\n return (\n <TweetSource\n data={data}\n indicator={indicator}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React from \"react\";\nimport { Skeleton } from \"@liberfi.io/ui\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetOriginal } from \"./tweet-original\";\nimport { TweetQuote } from \"./tweet-quote\";\nimport { TweetReply } from \"./tweet-reply\";\nimport { TweetRetweet } from \"./tweet-retweet\";\n\ntype Props = {\n data?: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n embed?: boolean;\n children?: React.ReactNode;\n loading?: boolean;\n};\n\n// ------------------------------------------------------------\nexport function TweetItem({\n data,\n headerActions,\n footerActions,\n embed = false,\n children,\n loading = false,\n}: Props) {\n if (loading || !data) {\n return <TweetSkeleton embed={embed} />;\n }\n\n const tweetType = data.tweet.type;\n\n // Render appropriate component based on tweet type\n const renderTweetComponent = () => {\n const commonProps = {\n data,\n headerActions,\n footerActions,\n embed,\n children,\n };\n\n switch (tweetType) {\n case \"reply\":\n return <TweetReply {...commonProps} />;\n case \"retweet\":\n return <TweetRetweet {...commonProps} />;\n case \"quote\":\n return <TweetQuote {...commonProps} />;\n default: // \"original\"\n return <TweetOriginal {...commonProps} />;\n }\n };\n\n return <div className=\"w-full\">{renderTweetComponent()}</div>;\n}\n\n// ------------------------------------------------------------\nfunction TweetSkeleton({ embed = false }: { embed?: boolean }) {\n const containerClass = embed\n ? \"bg-default-50 rounded-lg p-3 w-full mx-auto\"\n : \"bg-default-100 rounded-lg p-3 w-full mx-auto\";\n\n return (\n <div className={[\"flex flex-col gap-2\", containerClass].join(\" \")}>\n {/* User Info Skeleton */}\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"w-10 h-10 rounded-full\" />\n <div className=\"flex flex-col gap-1 flex-1\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-3 w-16\" />\n </div>\n <Skeleton className=\"h-3 w-12\" />\n </div>\n\n {/* Content Skeleton */}\n <div className=\"flex flex-col gap-2\">\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n\n {/* Media Skeleton */}\n <Skeleton className=\"h-48 w-full rounded-lg\" />\n\n {/* Actions Skeleton */}\n <div className=\"flex justify-between items-center pt-2\">\n <div className=\"flex gap-4\">\n <Skeleton className=\"h-6 w-16\" />\n <Skeleton className=\"h-6 w-16\" />\n <Skeleton className=\"h-6 w-16\" />\n </div>\n <Skeleton className=\"h-6 w-20\" />\n </div>\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { Avatar, Badge, Button, Image } from \"@liberfi.io/ui\";\nimport { formatPercent, SafeBigNumber } from \"@liberfi.io/utils\";\nimport { MediaToken } from \"../../../../types\";\n\ntype Props = {\n token: MediaToken;\n};\n\nexport function TweetTokenButton({ token }: Props) {\n const color = new SafeBigNumber(token.priceChange ?? \"0\").isPositive()\n ? \"primary\"\n : \"danger\";\n\n return (\n <Button\n color={color}\n variant=\"flat\"\n size=\"sm\"\n radius=\"full\"\n startContent={<TweetTokenIcon token={token} />}\n >\n <span>{token.symbol}</span>\n <span>\n {token.priceChange\n ? formatPercent(Number(token.priceChange) / 100)\n : \"--\"}\n </span>\n </Button>\n );\n}\n\nexport function TweetTokenIcon({ token }: Props) {\n const ChainIcon = useMemo(() => {\n return (\n <Image className=\"w-full h-full\" src={token.image} alt={token.chain} />\n );\n }, [token.chain, token.image]);\n\n return (\n <Badge\n className=\"w-2.5 h-2.5 p-0 border\"\n size=\"sm\"\n content={ChainIcon}\n shape=\"circle\"\n placement=\"bottom-right\"\n >\n <Avatar className=\"w-5 h-5\" radius=\"full\" src={token.image} />\n </Badge>\n );\n}\n","import { useCallback } from \"react\";\nimport { TweetMedia } from \"../../types\";\nimport { TweetTokenButton } from \"./tweet/tools/tweet-token-button\";\n// import { TweetTradeButton } from \"./tweet/tools/tweet-trade-button\";\nimport { TweetItem } from \"./tweet/tweet-item\";\n\ntype TweetsProps = {\n data: Array<TweetMedia>;\n loading: boolean;\n setIsPaused: (paused: boolean) => void;\n customHeaderActions?: (item: TweetMedia) => React.ReactNode;\n customFooterActions?: (item: TweetMedia) => React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function Tweets({\n data,\n loading,\n setIsPaused,\n customHeaderActions,\n customFooterActions,\n}: TweetsProps) {\n const footerActions = useCallback(\n (item: TweetMedia) => (\n <div className=\"flex gap-2.5 justify-between\">\n {item.token && <TweetTokenButton token={item.token} />}\n {customFooterActions?.(item)}\n {/* {item.token && <TweetTradeButton token={item.token} />} */}\n </div>\n ),\n [customFooterActions],\n );\n\n return (\n <div\n className=\"flex flex-col gap-2.5\"\n onMouseEnter={() => setIsPaused(true)}\n onMouseLeave={() => setIsPaused(false)}\n >\n {data.map((item: TweetMedia) => (\n <TweetItem\n key={item.id}\n data={item}\n headerActions={customHeaderActions?.(item)}\n footerActions={footerActions(item)}\n loading={loading}\n />\n ))}\n </div>\n );\n}\n","import { Skeleton } from \"@liberfi.io/ui\";\n\n// ------------------------------------------------------------\nexport function TweetSkeleton() {\n return (\n <div className=\"flex flex-col gap-2 bg-default-100 rounded-lg p-3 w-full mx-auto\">\n {/* User Info Skeleton */}\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"w-10 h-10 rounded-full\" />\n <div className=\"flex flex-col gap-1 flex-1\">\n <Skeleton className=\"h-4 w-40 rounded-md\" />\n <Skeleton className=\"h-3 w-32 rounded-md\" />\n </div>\n </div>\n\n {/* Content Skeleton */}\n <div className=\"flex flex-col gap-2\">\n <Skeleton className=\"h-4 w-full rounded-md\" />\n <Skeleton className=\"h-4 w-3/4 rounded-md\" />\n <Skeleton className=\"h-4 w-1/2 rounded-md\" />\n </div>\n\n {/* Media Skeleton */}\n <Skeleton className=\"h-48 w-full rounded-lg\" />\n </div>\n );\n}\n\nexport function TweetSkeletonList({ count = 3 }: { count: number }) {\n return (\n <div className=\"flex flex-col gap-2\">\n {Array.from({ length: count }).map((_, index) => (\n <TweetSkeleton key={index} />\n ))}\n </div>\n );\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { useMediaTrackRuntime } from \"../../hooks/useMediaTrackRuntime\";\nimport { TweetMedia } from \"../../types\";\n\nexport const useTweets = () => {\n const [medias, setMedias] = useState<Array<TweetMedia>>([]);\n const [loading, setLoading] = useState(true);\n const [isPaused, setIsPaused] = useState(false);\n\n const runtime = useMediaTrackRuntime();\n\n const handleMedia = useCallback(\n (media: TweetMedia) => {\n setMedias((prevMedias) => {\n const idx = prevMedias.findIndex((it) => it.id === media.id);\n let newMedias: Array<TweetMedia>;\n\n if (idx >= 0) {\n newMedias = prevMedias.map((item, index) =>\n index === idx ? media : item,\n );\n } else {\n if (isPaused) {\n return prevMedias;\n }\n newMedias = [media, ...prevMedias];\n }\n\n return newMedias.slice(0, 30);\n });\n setLoading(false);\n },\n [isPaused],\n );\n\n useEffect(() => {\n const subTweet = runtime.subscribe(\"x-monitor-basic\", handleMedia);\n const subTweetToken = runtime.subscribe(\"x-monitor-token\", handleMedia);\n return () => {\n subTweet.unsubscribe();\n subTweetToken.unsubscribe();\n };\n }, [runtime, handleMedia]);\n\n return { medias, loading, isPaused, setIsPaused };\n};\n","import { useEffect } from \"react\";\nimport { TweetMedia } from \"../../types\";\nimport { TweetSkeletonList } from \"./tweet/tweet-skeleton\";\nimport { useTweets } from \"./tweets.script\";\nimport { Tweets } from \"./tweets.ui\";\n\n// ------------------------------------------------------------\nexport type TweetsWidgetProps = {\n onPauseChange?: (paused: boolean) => void;\n customHeaderActions?: (item: TweetMedia) => React.ReactNode;\n customFooterActions?: (item: TweetMedia) => React.ReactNode;\n};\n\nexport function TweetsWidget({\n onPauseChange,\n customHeaderActions,\n customFooterActions,\n}: TweetsWidgetProps) {\n const { medias, loading, isPaused, setIsPaused } = useTweets();\n\n useEffect(() => {\n onPauseChange?.(isPaused);\n }, [isPaused, onPauseChange]);\n\n if (loading) {\n return <TweetSkeletonList count={3} />;\n }\n\n return (\n <Tweets\n data={medias}\n loading={loading}\n setIsPaused={setIsPaused}\n customHeaderActions={customHeaderActions}\n customFooterActions={customFooterActions}\n />\n );\n}\n","export type MediaTrackUnsubscribe = () => void;\n\nexport interface MediaTrackSubscription {\n unsubscribe: MediaTrackUnsubscribe;\n}\n\nexport interface MediaTrackRuntime<T = unknown> {\n readonly generation: number;\n connect(): void;\n disconnect(): void;\n setLocaleTransform(transform: ((payload: T) => T) | null): void;\n subscribe(channel: string, listener: (payload: T) => void): MediaTrackSubscription;\n publish(channel: string, payload: T): void;\n}\n\nexport function createMediaTrackRuntime<T = unknown>(): MediaTrackRuntime<T> {\n let generation = 0;\n let connected = false;\n let localeTransform: ((payload: T) => T) | null = null;\n const listeners = new Map<string, Set<(payload: T) => void>>();\n\n return {\n get generation() {\n return generation;\n },\n connect() {\n generation += 1;\n connected = true;\n },\n disconnect() {\n connected = false;\n },\n setLocaleTransform(transform) {\n localeTransform = transform;\n },\n subscribe(channel, listener) {\n let bucket = listeners.get(channel);\n if (!bucket) {\n bucket = new Set();\n listeners.set(channel, bucket);\n }\n bucket.add(listener);\n let unsubscribed = false;\n return {\n unsubscribe() {\n if (unsubscribed) return;\n unsubscribed = true;\n const current = listeners.get(channel);\n current?.delete(listener);\n if (current && current.size === 0) {\n listeners.delete(channel);\n }\n },\n };\n },\n publish(channel, payload) {\n if (!connected) return;\n const next = localeTransform ? localeTransform(payload) : payload;\n listeners.get(channel)?.forEach((listener) => listener(next));\n },\n };\n}\n","import { PropsWithChildren, useContext, useEffect, useMemo } from \"react\";\nimport { MediaTrackContext } from \"../context\";\nimport { MediaTrackRuntimeContext } from \"../context/MediaTrackRuntimeContext\";\nimport { createMediaTrackRuntime } from \"../runtime/media-track-runtime\";\nimport type { IMediaTrackClient, TweetMedia } from \"../types\";\n\nexport type MediaTrackProviderProps = PropsWithChildren<{\n client: IMediaTrackClient;\n}>;\n\nexport function MediaTrackProvider({\n client,\n children,\n}: MediaTrackProviderProps) {\n const runtime = useMemo(() => createMediaTrackRuntime<TweetMedia>(), []);\n\n return (\n <MediaTrackContext.Provider value={{ client }}>\n <MediaTrackRuntimeContext.Provider value={runtime}>\n <MediaTrackClientBridge client={client} />\n {children}\n </MediaTrackRuntimeContext.Provider>\n </MediaTrackContext.Provider>\n );\n}\n\nfunction MediaTrackClientBridge({ client }: { client: IMediaTrackClient }) {\n const runtime = useContext(MediaTrackRuntimeContext);\n useEffect(() => {\n if (!runtime) return;\n runtime.connect();\n const basic = client.subscribeTweetMedia({\n callback: (media) => runtime.publish(\"x-monitor-basic\", media),\n });\n const token = client.subscribeTweetMediaToken({\n callback: (media) => runtime.publish(\"x-monitor-token\", media),\n });\n return () => {\n basic.unsubscribe();\n token.unsubscribe();\n runtime.disconnect();\n };\n }, [client, runtime]);\n return null;\n}\n"]}
1
+ {"version":3,"sources":["../src/components/tweets/tweet/media/media-image.tsx","../src/components/tweets/tweet/media/media-video.tsx","../src/components/tweets/tweet/media/medias.tsx","../src/components/tweets/tweet/user/user-avatar.tsx","../src/components/tweets/tweet/user/user-info.tsx","../src/context/MediaTrackContext.ts","../src/context/MediaTrackRuntimeContext.ts","../src/hooks/useMediaTrackContext.ts","../src/hooks/useMediaTrackClient.ts","../src/hooks/useGenerateTweetMediaMemeMutation.ts","../src/hooks/useMediaTrackRuntime.ts","../src/hooks/useTranslateTweetMediaQuery.ts","../src/utils/parseText.tsx","../src/components/tweets/tweet/tools/translate.tsx","../src/components/tweets/tweet/tools/text-expand.tsx","../src/components/tweets/tweet/content/index.tsx","../src/components/tweets/tweet/tweet-source.tsx","../src/components/tweets/tweet/tweet-original.tsx","../src/components/tweets/tweet/tweet-quote.tsx","../src/components/tweets/tweet/tweet-reply.tsx","../src/components/tweets/tweet/tweet-retweet.tsx","../src/components/tweets/tweet/tweet-item.tsx","../src/components/tweets/tweet/tools/tweet-token-button.tsx","../src/components/tweets/tweets.ui.tsx","../src/components/tweets/tweet/tweet-skeleton.tsx","../src/components/tweets/tweets.script.ts","../src/components/tweets/tweets.widget.tsx","../src/runtime/media-track-runtime.ts","../src/providers/MediaTrackProvider.tsx"],"names":["MediaImage","src","isLoaded","setTrue","useBoolean","jsx","Skeleton","MediaVideo","Medias","medias","tweetHref","images","media","videos","renderVideos","video","renderImages","image","Link","jsxs","UserAvatar","url","name","size","fallbackName","useMemo","Avatar","UserInfo","user","renderTimestamp","renderActions","twitterUserUrl","MediaTrackContext","createContext","MediaTrackRuntimeContext","useMediaTrackContext","context","useContext","useMediaTrackClient","client","useGenerateTweetMediaMemeMutation","options","useMutation","params","useMediaTrackRuntime","runtime","translateTweetMedia","targetLanguage","useTranslateTweetMediaMutation","parseText","text","urlRegex","hashtagRegex","symbolRegex","matches","match","matchIndex","a","b","parts","lastIndex","key","item","e","hashtagUrl","Translate","data","embed","isTranslate","toggle","t","i18n","useTranslation","isTranslating","translatedText","setTranslatedText","useState","handleTranslate","useCallback","parsedText","Fragment","TranslateIcon","cn","TextExpand","isExpanded","onToggleExpand","renderExpand","ChevronUpIcon","ChevronDownIcon","Content","content","onLoad","ref","useRef","parsedContent","useEffect","current","TweetSource","headerActions","footerActions","indicator","children","formatAge","useLocalizedTimeFormatter","setIsExpanded","containerClass","tweet","age","useTickAge","twitterTweetUrl","TweetOriginal","TweetQuote","hasSource","TweetReply","sourceTweet","TweetRetweet","TweetItem","loading","TweetSkeleton","tweetType","commonProps","TweetTokenButton","token","color","SafeBigNumber","Button","TweetTokenIcon","formatPercent","ChainIcon","Image","Badge","Tweets","setIsPaused","customHeaderActions","customFooterActions","TweetSkeletonList","count","_","index","useTweets","setMedias","setLoading","isPaused","handleMedia","prevMedias","idx","it","newMedias","subTweet","subTweetToken","TweetsWidget","onPauseChange","createMediaTrackRuntime","generation","connected","localeTransform","listeners","transform","channel","listener","bucket","unsubscribed","payload","next","MediaTrackProvider","active","MediaTrackClientBridge","basic"],"mappings":"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","file":"index.mjs","sourcesContent":["import { useBoolean } from \"@liberfi.io/hooks\";\nimport { Skeleton } from \"@liberfi.io/ui\";\n\ntype Props = {\n src: string;\n};\n\n// ------------------------------------------------------------\nexport function MediaImage({ src }: Props) {\n const [isLoaded, { setTrue }] = useBoolean(false);\n if (!src) return null;\n\n return (\n <Skeleton isLoaded={isLoaded} className=\"w-full h-auto\">\n <img\n src={src}\n className=\"w-full h-full object-cover aspect-video\"\n onLoad={() => {\n setTrue();\n }}\n />\n </Skeleton>\n );\n}\n","type Props = {\n src: string;\n};\n\n// ------------------------------------------------------------\nexport function MediaVideo({ src }: Props) {\n if (!src) return null;\n\n return (\n <div className=\"w-full h-full overflow-hidden rounded-md mt-2\">\n <iframe\n className=\"w-full h-full aspect-video\"\n src={src}\n allowFullScreen\n />\n </div>\n );\n}\n","import { Link } from \"@liberfi.io/ui\";\nimport { TweetContentMedia } from \"../../../../types\";\nimport { MediaImage } from \"./media-image\";\nimport { MediaVideo } from \"./media-video\";\n\ntype Props = {\n medias: Array<TweetContentMedia>;\n tweetHref: string;\n};\n\nexport function Medias({ medias, tweetHref }: Props) {\n const images = medias.filter((media) => media.type === \"image\");\n const videos = medias.filter((media) => media.type === \"video\");\n\n const renderVideos = () => {\n if (!videos.length) return null;\n return (\n <div className={`grid grid-cols-1 gap-[1px] overflow-hidden rounded-md`}>\n {videos.map((video) => (\n <MediaVideo key={video.url} src={video.url} />\n ))}\n </div>\n );\n };\n\n const renderImages = () => {\n if (!images.length) return null;\n return (\n <div className={`grid grid-cols-1 gap-[1px] overflow-hidden rounded-md`}>\n {images.map((image) => (\n <Link key={image.url} href={tweetHref} target=\"_blank\">\n <MediaImage src={image.url} />\n </Link>\n ))}\n </div>\n );\n };\n\n return (\n <div className=\"flex flex-col gap-2\">\n {renderVideos()}\n {renderImages()}\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { Avatar, Skeleton } from \"@liberfi.io/ui\";\n\ntype Props = {\n url?: string;\n name?: string;\n size?: number;\n};\n\nexport function UserAvatar({ url, name = \"\", size = 36 }: Props) {\n const fallbackName = useMemo(() => (name ? name.slice(0, 2) : \"N/A\"), [name]);\n\n return (\n <Skeleton\n className=\"flex rounded-full flex-shrink-0\"\n style={{ width: size, height: size }}\n isLoaded={!!url}\n >\n <Avatar\n size=\"md\"\n color=\"primary\"\n radius=\"full\"\n showFallback\n name={fallbackName}\n src={url}\n style={{ width: size, height: size }}\n />\n </Skeleton>\n );\n}\n","import React from \"react\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetUser } from \"../../../../types\";\nimport { UserAvatar } from \"./user-avatar\";\n\ntype Props = {\n user: TweetUser;\n renderTimestamp?: React.ReactNode;\n renderActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function UserInfo({ user, renderTimestamp, renderActions }: Props) {\n return (\n <div className=\"flex items-center justify-between gap-1\">\n <div className=\"flex items-center gap-1\">\n <UserAvatar url={user.avatar} name={user.username} />\n <div className=\"flex flex-col gap-0.5\">\n <div className=\"flex flex-row items-baseline gap-1\">\n <span className=\"text-foreground font-semibold truncate leading-none\">\n {user.username}\n </span>\n {renderTimestamp}\n </div>\n <Link\n target=\"_blank\"\n underline=\"hover\"\n className=\"text-text-muted text-sm leading-none\"\n href={twitterUserUrl(user.screenName ?? user.username)}\n >\n @{user.screenName ?? user.username}\n </Link>\n </div>\n </div>\n {renderActions}\n </div>\n );\n}\n","import { createContext } from \"react\";\nimport { IMediaTrackClient } from \"../types\";\n\nexport interface MediaTrackContextValue {\n client: IMediaTrackClient;\n}\n\nexport const MediaTrackContext = createContext<MediaTrackContextValue>(\n {} as MediaTrackContextValue,\n);\n","import { createContext } from \"react\";\nimport type { TweetMedia } from \"../types\";\nimport type { MediaTrackRuntime } from \"../runtime/media-track-runtime\";\n\nexport const MediaTrackRuntimeContext =\n createContext<MediaTrackRuntime<TweetMedia> | null>(null);\n","import { useContext } from \"react\";\nimport { MediaTrackContext } from \"../context\";\n\nexport function useMediaTrackContext() {\n const context = useContext(MediaTrackContext);\n if (!context) {\n throw new Error(\n \"useMediaTrackContext must be used within a MediaTrackProvider\",\n );\n }\n return context;\n}\n","import { useMediaTrackContext } from \"./useMediaTrackContext\";\n\nexport function useMediaTrackClient() {\n const { client } = useMediaTrackContext();\n return client;\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport { GeneratedMemeInfo, TweetMedia } from \"../types\";\nimport { useMediaTrackClient } from \"./useMediaTrackClient\";\n\nexport function useGenerateTweetMediaMemeMutation(\n options: Omit<\n UseMutationOptions<GeneratedMemeInfo, Error, TweetMedia, string[]>,\n \"mutationFn\"\n > = {},\n) {\n const client = useMediaTrackClient();\n return useMutation({\n mutationFn: async (params: TweetMedia) => client.generateMeme(params),\n ...options,\n });\n}\n","import { useContext } from \"react\";\nimport { MediaTrackRuntimeContext } from \"../context/MediaTrackRuntimeContext\";\n\nexport function useMediaTrackRuntime() {\n const runtime = useContext(MediaTrackRuntimeContext);\n if (!runtime) {\n throw new Error(\n \"useMediaTrackRuntime must be used within a MediaTrackProvider\",\n );\n }\n return runtime;\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport { LocaleCode } from \"@liberfi.io/i18n\";\nimport { IMediaTrackClient, TweetMedia } from \"../types\";\nimport { useMediaTrackClient } from \"./useMediaTrackClient\";\n\nexport interface UseTranslateTweetMediaParams {\n media: TweetMedia;\n targetLanguage: LocaleCode;\n options?: {\n sourceLanguage?: LocaleCode;\n sourceTweet?: boolean;\n };\n}\n\nexport async function translateTweetMedia(\n client: IMediaTrackClient,\n { media, targetLanguage, options }: UseTranslateTweetMediaParams,\n) {\n return await client.translate(media, targetLanguage, options);\n}\n\nexport function useTranslateTweetMediaMutation(\n options: Omit<\n UseMutationOptions<string, Error, UseTranslateTweetMediaParams>,\n \"mutationFn\"\n > = {},\n) {\n const client = useMediaTrackClient();\n return useMutation({\n mutationFn: async (params: UseTranslateTweetMediaParams) =>\n translateTweetMedia(client, params),\n ...options,\n });\n}\n","interface MatchItem {\n index: number;\n length: number;\n text: string;\n type: \"url\" | \"hashtag\" | \"symbol\";\n}\n\nexport function parseText(text: string): (string | React.ReactElement)[] {\n const urlRegex = /(https?:\\/\\/[^\\s]+|www\\.[^\\s]+)/gi;\n const hashtagRegex = /#[\\w]+/g;\n const symbolRegex = /\\$[A-Za-z][A-Za-z0-9_]*/g;\n\n const matches: MatchItem[] = [];\n let match: RegExpExecArray | null;\n\n while ((match = urlRegex.exec(text)) !== null) {\n matches.push({\n index: match.index,\n length: match[0].length,\n text: match[0],\n type: \"url\",\n });\n }\n\n while ((match = hashtagRegex.exec(text)) !== null) {\n const matchIndex = match.index;\n const overlaps = matches.some(\n (m) => matchIndex >= m.index && matchIndex < m.index + m.length,\n );\n if (!overlaps) {\n matches.push({\n index: matchIndex,\n length: match[0].length,\n text: match[0],\n type: \"hashtag\",\n });\n }\n }\n\n while ((match = symbolRegex.exec(text)) !== null) {\n const matchIndex = match.index;\n const overlaps = matches.some(\n (m) => matchIndex >= m.index && matchIndex < m.index + m.length,\n );\n if (!overlaps) {\n matches.push({\n index: matchIndex,\n length: match[0].length,\n text: match[0],\n type: \"symbol\",\n });\n }\n }\n\n matches.sort((a, b) => a.index - b.index);\n\n const parts: (string | React.ReactElement)[] = [];\n let lastIndex = 0;\n let key = 0;\n\n matches.forEach((item) => {\n if (item.index > lastIndex) {\n parts.push(text.slice(lastIndex, item.index));\n }\n\n if (item.type === \"url\") {\n const url = item.text.startsWith(\"http\")\n ? item.text\n : `https://${item.text}`;\n parts.push(\n <a\n key={key++}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n onClick={(e) => e.stopPropagation()}\n >\n {item.text}\n </a>,\n );\n } else if (item.type === \"hashtag\") {\n const hashtag = item.text.slice(1); // 移除 #\n const hashtagUrl = `https://x.com/hashtag/${hashtag}`;\n parts.push(\n <a\n key={key++}\n href={hashtagUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n onClick={(e) => e.stopPropagation()}\n >\n {item.text}\n </a>,\n );\n } else if (item.type === \"symbol\") {\n parts.push(\n <span key={key++} className=\"text-primary\">\n {item.text}\n </span>,\n );\n }\n\n lastIndex = item.index + item.length;\n });\n\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n\n return parts.length > 0 ? parts : [text];\n}\n","import React, { MouseEvent, useCallback, useState } from \"react\";\nimport { useBoolean } from \"@liberfi.io/hooks\";\nimport { LocaleCode, useTranslation } from \"@liberfi.io/i18n\";\nimport { cn, Skeleton, TranslateIcon } from \"@liberfi.io/ui\";\nimport { useTranslateTweetMediaMutation } from \"../../../../hooks\";\nimport { TweetMedia } from \"../../../../types\";\nimport { parseText } from \"../../../../utils\";\n\ntype Props = {\n data: TweetMedia;\n embed?: boolean;\n text: string;\n renderActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function Translate({ data, embed, renderActions }: Props) {\n const [isTranslate, { toggle }] = useBoolean(false);\n\n const { t, i18n } = useTranslation();\n\n const { mutateAsync: translateTweetMedia, isPending: isTranslating } =\n useTranslateTweetMediaMutation();\n\n const [translatedText, setTranslatedText] = useState<\n (string | React.ReactElement)[] | null\n >(null);\n\n const handleTranslate = useCallback(\n async (e: MouseEvent<HTMLDivElement>) => {\n e.stopPropagation();\n toggle();\n if (!translatedText) {\n const text = await translateTweetMedia({\n media: data,\n targetLanguage: i18n.language as LocaleCode,\n options: {\n sourceTweet: embed,\n },\n });\n const parsedText = parseText(text);\n setTranslatedText(parsedText);\n }\n },\n [toggle, translateTweetMedia, data, i18n.language, translatedText, embed],\n );\n\n return (\n <>\n <div className=\"flex items-center gap-1 text-xs\">\n <div\n onClick={handleTranslate}\n className=\"flex items-center gap-0.5 cursor-pointer text-primary hover:text-foreground\"\n >\n <TranslateIcon width=\"14\" height=\"14\" />\n {isTranslate\n ? t(\"mediaTrack.tweets.translate.hide\")\n : t(\"mediaTrack.tweets.translate.show\")}\n </div>\n {renderActions}\n </div>\n <div\n className={cn(!isTranslate && \"hidden\")}\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n {isTranslate && (\n <div className=\"bg-content2 rounded-md p-2 text-text-primary text-sm leading-5\">\n {translatedText}\n {isTranslating && <Skeleton className=\"w-full h-4 rounded-md\" />}\n </div>\n )}\n </div>\n </>\n );\n}\n","import { useTranslation } from \"@liberfi.io/i18n\";\nimport { ChevronDownIcon, ChevronUpIcon } from \"@liberfi.io/ui\";\n\ntype Props = {\n isExpanded?: boolean;\n onToggleExpand?: (expanded: boolean) => void;\n};\n\nexport function TextExpand({ isExpanded, onToggleExpand }: Props) {\n const { t } = useTranslation();\n const renderExpand = () => {\n if (isExpanded) {\n return (\n <>\n <ChevronUpIcon\n className=\"border border-current\"\n width=\"12\"\n height=\"12\"\n />\n &nbsp;{t(\"mediaTrack.tweets.collapse\")}\n </>\n );\n }\n\n return (\n <>\n <ChevronDownIcon\n className=\"border border-current\"\n width=\"12\"\n height=\"12\"\n />\n &nbsp;{t(\"mediaTrack.tweets.expand\")}\n </>\n );\n };\n\n if (isExpanded === undefined) return null;\n\n return (\n <div className=\"flex items-center gap-1\">\n <div className=\"w-px h-2.5 bg-line-300\" />\n <button\n onClick={(e) => {\n e.stopPropagation();\n onToggleExpand?.(!isExpanded);\n }}\n className=\"flex items-center text-text-muted hover:text-foreground text-xs\"\n >\n {renderExpand()}\n </button>\n </div>\n );\n}\n","import { useEffect, useMemo, useRef } from \"react\";\nimport { parseText } from \"../../../../utils\";\n\ntype Props = {\n content: string;\n isExpanded?: boolean;\n onLoad?: () => void;\n};\n\n// ------------------------------------------------------------\nexport function Content({ content, isExpanded = false, onLoad }: Props) {\n const ref = useRef<HTMLDivElement>(null);\n\n const parsedContent = useMemo(() => parseText(content), [content]);\n\n useEffect(() => {\n const current = ref.current;\n if (!onLoad || !current) return;\n if (current.scrollHeight > current.clientHeight) {\n onLoad?.();\n }\n }, [isExpanded, onLoad]);\n\n return (\n <div\n ref={ref}\n className={[\n \"text-text-primary text-sm leading-5\",\n !isExpanded ? \"line-clamp-3\" : \"\",\n ].join(\" \")}\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n {parsedContent}\n </div>\n );\n}\n","import React, { useMemo, useState } from \"react\";\nimport { useTickAge } from \"@liberfi.io/hooks\";\nimport { useLocalizedTimeFormatter } from \"@liberfi.io/i18n\";\nimport { cn } from \"@liberfi.io/ui\";\nimport { twitterTweetUrl } from \"@liberfi.io/utils\";\nimport { Tweet, TweetMedia } from \"../../../types\";\nimport { Content } from \"./content\";\nimport { Medias } from \"./media\";\nimport { Translate, TextExpand } from \"./tools\";\nimport { UserInfo } from \"./user\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n embed?: boolean;\n indicator?: React.ReactNode;\n children?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetSource({\n data,\n headerActions,\n footerActions,\n embed = false,\n indicator,\n children,\n}: Props) {\n const { formatAge } = useLocalizedTimeFormatter();\n const [isExpanded, setIsExpanded] = useState<boolean | undefined>(undefined);\n\n const containerClass = useMemo(() => {\n return embed\n ? \"bg-default-50 rounded-lg p-3 w-full mx-auto\"\n : \"bg-default-100 hover:bg-default-200 rounded-lg p-3 w-full mx-auto\";\n }, [embed]);\n\n const tweet = useMemo(\n () => (embed ? data.sourceTweet! : data.tweet),\n [data, embed],\n );\n\n const age = useTickAge((tweet as Tweet).timestamp);\n\n return (\n <div\n className={cn(\"flex flex-col gap-1.5 cursor-pointer\", containerClass)}\n onClick={() => {\n window.open(twitterTweetUrl(tweet.tweetId), \"_blank\");\n }}\n >\n {/* -------- USER INFO -------- */}\n <UserInfo\n user={tweet.user}\n renderTimestamp={\n embed ? undefined : (\n <div className=\"text-xs text-primary\">{formatAge(age)}</div>\n )\n }\n renderActions={headerActions}\n />\n\n {/* -------- MESSAGE TYPE INDICATOR -------- */}\n {indicator}\n\n {/* -------- CONTENT -------- */}\n {tweet.content.text && (\n <Content\n content={tweet.content.text}\n isExpanded={isExpanded}\n onLoad={() => setIsExpanded(false)}\n />\n )}\n\n {/* -------- TOOLS -------- */}\n {tweet.content.text && (\n <Translate\n data={data}\n embed={embed}\n text={tweet.content.text}\n renderActions={\n <TextExpand\n isExpanded={isExpanded}\n onToggleExpand={setIsExpanded}\n />\n }\n />\n )}\n\n {/* -------- MEDIA -------- */}\n <div\n className={cn(\n (!tweet.content.medias || tweet.content.medias.length === 0) &&\n \"hidden\",\n )}\n >\n {tweet.content.medias && tweet.content.medias.length > 0 && (\n <Medias\n medias={tweet.content.medias}\n tweetHref={twitterTweetUrl(tweet.tweetId)}\n />\n )}\n </div>\n\n {/* -------- CHILDREN -------- */}\n {children}\n\n {/* -------- Custom ACTIONS -------- */}\n {footerActions}\n </div>\n );\n}\n","import React from \"react\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetOriginal({ data, headerActions, footerActions }: Props) {\n return (\n <TweetSource\n data={data}\n headerActions={headerActions}\n footerActions={footerActions}\n />\n );\n}\n","import React from \"react\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetQuote({ data, headerActions, footerActions }: Props) {\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n return (\n <TweetSource\n data={data}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React, { useMemo } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetReply({ data, headerActions, footerActions }: Props) {\n const { t } = useTranslation();\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n const indicator = useMemo(\n () => (\n <div className=\"flex items-center gap-2 text-sm\">\n <span>{t(\"mediaTrack.replyingTo\")}</span>\n {hasSource && (\n <Link\n className=\"text-sm\"\n underline=\"hover\"\n target=\"_blank\"\n href={twitterUserUrl(\n sourceTweet.user.screenName ?? sourceTweet.user.username,\n )}\n >\n @{sourceTweet.user.screenName ?? sourceTweet.user.username}\n </Link>\n )}\n </div>\n ),\n [hasSource, sourceTweet, t],\n );\n\n return (\n <TweetSource\n data={data}\n indicator={indicator}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React, { useMemo } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { Link } from \"@liberfi.io/ui\";\nimport { twitterUserUrl } from \"@liberfi.io/utils\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetSource } from \"./tweet-source\";\n\ntype Props = {\n data: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function TweetRetweet({ data, headerActions, footerActions }: Props) {\n const { t } = useTranslation();\n const sourceTweet = data.sourceTweet;\n const hasSource = !!sourceTweet;\n\n const indicator = useMemo(\n () => (\n <div className=\"flex items-center gap-2 text-sm\">\n <span>{t(\"mediaTrack.retweetedBy\")}</span>\n {hasSource && (\n <Link\n className=\"text-sm\"\n underline=\"hover\"\n target=\"_blank\"\n href={twitterUserUrl(\n sourceTweet.user.screenName ?? sourceTweet.user.username,\n )}\n >\n @{sourceTweet.user.screenName ?? sourceTweet.user.username}\n </Link>\n )}\n </div>\n ),\n [hasSource, sourceTweet, t],\n );\n\n return (\n <TweetSource\n data={data}\n indicator={indicator}\n headerActions={headerActions}\n footerActions={footerActions}\n >\n {hasSource ? <TweetSource data={data} embed /> : null}\n </TweetSource>\n );\n}\n","import React from \"react\";\nimport { Skeleton } from \"@liberfi.io/ui\";\nimport { TweetMedia } from \"../../../types\";\nimport { TweetOriginal } from \"./tweet-original\";\nimport { TweetQuote } from \"./tweet-quote\";\nimport { TweetReply } from \"./tweet-reply\";\nimport { TweetRetweet } from \"./tweet-retweet\";\n\ntype Props = {\n data?: TweetMedia;\n headerActions?: React.ReactNode;\n footerActions?: React.ReactNode;\n embed?: boolean;\n children?: React.ReactNode;\n loading?: boolean;\n};\n\n// ------------------------------------------------------------\nexport function TweetItem({\n data,\n headerActions,\n footerActions,\n embed = false,\n children,\n loading = false,\n}: Props) {\n if (loading || !data) {\n return <TweetSkeleton embed={embed} />;\n }\n\n const tweetType = data.tweet.type;\n\n // Render appropriate component based on tweet type\n const renderTweetComponent = () => {\n const commonProps = {\n data,\n headerActions,\n footerActions,\n embed,\n children,\n };\n\n switch (tweetType) {\n case \"reply\":\n return <TweetReply {...commonProps} />;\n case \"retweet\":\n return <TweetRetweet {...commonProps} />;\n case \"quote\":\n return <TweetQuote {...commonProps} />;\n default: // \"original\"\n return <TweetOriginal {...commonProps} />;\n }\n };\n\n return <div className=\"w-full\">{renderTweetComponent()}</div>;\n}\n\n// ------------------------------------------------------------\nfunction TweetSkeleton({ embed = false }: { embed?: boolean }) {\n const containerClass = embed\n ? \"bg-default-50 rounded-lg p-3 w-full mx-auto\"\n : \"bg-default-100 rounded-lg p-3 w-full mx-auto\";\n\n return (\n <div className={[\"flex flex-col gap-2\", containerClass].join(\" \")}>\n {/* User Info Skeleton */}\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"w-10 h-10 rounded-full\" />\n <div className=\"flex flex-col gap-1 flex-1\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-3 w-16\" />\n </div>\n <Skeleton className=\"h-3 w-12\" />\n </div>\n\n {/* Content Skeleton */}\n <div className=\"flex flex-col gap-2\">\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n\n {/* Media Skeleton */}\n <Skeleton className=\"h-48 w-full rounded-lg\" />\n\n {/* Actions Skeleton */}\n <div className=\"flex justify-between items-center pt-2\">\n <div className=\"flex gap-4\">\n <Skeleton className=\"h-6 w-16\" />\n <Skeleton className=\"h-6 w-16\" />\n <Skeleton className=\"h-6 w-16\" />\n </div>\n <Skeleton className=\"h-6 w-20\" />\n </div>\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { Avatar, Badge, Button, Image } from \"@liberfi.io/ui\";\nimport { formatPercent, SafeBigNumber } from \"@liberfi.io/utils\";\nimport { MediaToken } from \"../../../../types\";\n\ntype Props = {\n token: MediaToken;\n};\n\nexport function TweetTokenButton({ token }: Props) {\n const color = new SafeBigNumber(token.priceChange ?? \"0\").isPositive()\n ? \"primary\"\n : \"danger\";\n\n return (\n <Button\n color={color}\n variant=\"flat\"\n size=\"sm\"\n radius=\"full\"\n startContent={<TweetTokenIcon token={token} />}\n >\n <span>{token.symbol}</span>\n <span>\n {token.priceChange\n ? formatPercent(Number(token.priceChange) / 100)\n : \"--\"}\n </span>\n </Button>\n );\n}\n\nexport function TweetTokenIcon({ token }: Props) {\n const ChainIcon = useMemo(() => {\n return (\n <Image className=\"w-full h-full\" src={token.image} alt={token.chain} />\n );\n }, [token.chain, token.image]);\n\n return (\n <Badge\n className=\"w-2.5 h-2.5 p-0 border\"\n size=\"sm\"\n content={ChainIcon}\n shape=\"circle\"\n placement=\"bottom-right\"\n >\n <Avatar className=\"w-5 h-5\" radius=\"full\" src={token.image} />\n </Badge>\n );\n}\n","import { useCallback } from \"react\";\nimport { TweetMedia } from \"../../types\";\nimport { TweetTokenButton } from \"./tweet/tools/tweet-token-button\";\n// import { TweetTradeButton } from \"./tweet/tools/tweet-trade-button\";\nimport { TweetItem } from \"./tweet/tweet-item\";\n\ntype TweetsProps = {\n data: Array<TweetMedia>;\n loading: boolean;\n setIsPaused: (paused: boolean) => void;\n customHeaderActions?: (item: TweetMedia) => React.ReactNode;\n customFooterActions?: (item: TweetMedia) => React.ReactNode;\n};\n\n// ------------------------------------------------------------\nexport function Tweets({\n data,\n loading,\n setIsPaused,\n customHeaderActions,\n customFooterActions,\n}: TweetsProps) {\n const footerActions = useCallback(\n (item: TweetMedia) => (\n <div className=\"flex gap-2.5 justify-between\">\n {item.token && <TweetTokenButton token={item.token} />}\n {customFooterActions?.(item)}\n {/* {item.token && <TweetTradeButton token={item.token} />} */}\n </div>\n ),\n [customFooterActions],\n );\n\n return (\n <div\n className=\"flex flex-col gap-2.5\"\n onMouseEnter={() => setIsPaused(true)}\n onMouseLeave={() => setIsPaused(false)}\n >\n {data.map((item: TweetMedia) => (\n <TweetItem\n key={item.id}\n data={item}\n headerActions={customHeaderActions?.(item)}\n footerActions={footerActions(item)}\n loading={loading}\n />\n ))}\n </div>\n );\n}\n","import { Skeleton } from \"@liberfi.io/ui\";\n\n// ------------------------------------------------------------\nexport function TweetSkeleton() {\n return (\n <div className=\"flex flex-col gap-2 bg-default-100 rounded-lg p-3 w-full mx-auto\">\n {/* User Info Skeleton */}\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"w-10 h-10 rounded-full\" />\n <div className=\"flex flex-col gap-1 flex-1\">\n <Skeleton className=\"h-4 w-40 rounded-md\" />\n <Skeleton className=\"h-3 w-32 rounded-md\" />\n </div>\n </div>\n\n {/* Content Skeleton */}\n <div className=\"flex flex-col gap-2\">\n <Skeleton className=\"h-4 w-full rounded-md\" />\n <Skeleton className=\"h-4 w-3/4 rounded-md\" />\n <Skeleton className=\"h-4 w-1/2 rounded-md\" />\n </div>\n\n {/* Media Skeleton */}\n <Skeleton className=\"h-48 w-full rounded-lg\" />\n </div>\n );\n}\n\nexport function TweetSkeletonList({ count = 3 }: { count: number }) {\n return (\n <div className=\"flex flex-col gap-2\">\n {Array.from({ length: count }).map((_, index) => (\n <TweetSkeleton key={index} />\n ))}\n </div>\n );\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { useMediaTrackRuntime } from \"../../hooks/useMediaTrackRuntime\";\nimport { TweetMedia } from \"../../types\";\n\nexport const useTweets = () => {\n const [medias, setMedias] = useState<Array<TweetMedia>>([]);\n const [loading, setLoading] = useState(true);\n const [isPaused, setIsPaused] = useState(false);\n\n const runtime = useMediaTrackRuntime();\n\n const handleMedia = useCallback(\n (media: TweetMedia) => {\n setMedias((prevMedias) => {\n const idx = prevMedias.findIndex((it) => it.id === media.id);\n let newMedias: Array<TweetMedia>;\n\n if (idx >= 0) {\n newMedias = prevMedias.map((item, index) =>\n index === idx ? media : item,\n );\n } else {\n if (isPaused) {\n return prevMedias;\n }\n newMedias = [media, ...prevMedias];\n }\n\n return newMedias.slice(0, 30);\n });\n setLoading(false);\n },\n [isPaused],\n );\n\n useEffect(() => {\n const subTweet = runtime.subscribe(\"x-monitor-basic\", handleMedia);\n const subTweetToken = runtime.subscribe(\"x-monitor-token\", handleMedia);\n return () => {\n subTweet.unsubscribe();\n subTweetToken.unsubscribe();\n };\n }, [runtime, handleMedia]);\n\n return { medias, loading, isPaused, setIsPaused };\n};\n","import { useEffect } from \"react\";\nimport { TweetMedia } from \"../../types\";\nimport { TweetSkeletonList } from \"./tweet/tweet-skeleton\";\nimport { useTweets } from \"./tweets.script\";\nimport { Tweets } from \"./tweets.ui\";\n\n// ------------------------------------------------------------\nexport type TweetsWidgetProps = {\n onPauseChange?: (paused: boolean) => void;\n customHeaderActions?: (item: TweetMedia) => React.ReactNode;\n customFooterActions?: (item: TweetMedia) => React.ReactNode;\n};\n\nexport function TweetsWidget({\n onPauseChange,\n customHeaderActions,\n customFooterActions,\n}: TweetsWidgetProps) {\n const { medias, loading, isPaused, setIsPaused } = useTweets();\n\n useEffect(() => {\n onPauseChange?.(isPaused);\n }, [isPaused, onPauseChange]);\n\n if (loading) {\n return <TweetSkeletonList count={3} />;\n }\n\n return (\n <Tweets\n data={medias}\n loading={loading}\n setIsPaused={setIsPaused}\n customHeaderActions={customHeaderActions}\n customFooterActions={customFooterActions}\n />\n );\n}\n","export type MediaTrackUnsubscribe = () => void;\n\nexport interface MediaTrackSubscription {\n unsubscribe: MediaTrackUnsubscribe;\n}\n\nexport interface MediaTrackRuntime<T = unknown> {\n readonly generation: number;\n connect(): void;\n disconnect(): void;\n setLocaleTransform(transform: ((payload: T) => T) | null): void;\n subscribe(channel: string, listener: (payload: T) => void): MediaTrackSubscription;\n publish(channel: string, payload: T): void;\n}\n\nexport function createMediaTrackRuntime<T = unknown>(): MediaTrackRuntime<T> {\n let generation = 0;\n let connected = false;\n let localeTransform: ((payload: T) => T) | null = null;\n const listeners = new Map<string, Set<(payload: T) => void>>();\n\n return {\n get generation() {\n return generation;\n },\n connect() {\n generation += 1;\n connected = true;\n },\n disconnect() {\n connected = false;\n },\n setLocaleTransform(transform) {\n localeTransform = transform;\n },\n subscribe(channel, listener) {\n let bucket = listeners.get(channel);\n if (!bucket) {\n bucket = new Set();\n listeners.set(channel, bucket);\n }\n bucket.add(listener);\n let unsubscribed = false;\n return {\n unsubscribe() {\n if (unsubscribed) return;\n unsubscribed = true;\n const current = listeners.get(channel);\n current?.delete(listener);\n if (current && current.size === 0) {\n listeners.delete(channel);\n }\n },\n };\n },\n publish(channel, payload) {\n if (!connected) return;\n const next = localeTransform ? localeTransform(payload) : payload;\n listeners.get(channel)?.forEach((listener) => listener(next));\n },\n };\n}\n","import { PropsWithChildren, useContext, useEffect, useMemo } from \"react\";\nimport { MediaTrackContext } from \"../context\";\nimport { MediaTrackRuntimeContext } from \"../context/MediaTrackRuntimeContext\";\nimport { createMediaTrackRuntime } from \"../runtime/media-track-runtime\";\nimport type { IMediaTrackClient, TweetMedia } from \"../types\";\n\nexport type MediaTrackProviderProps = PropsWithChildren<{\n client: IMediaTrackClient;\n active?: boolean;\n}>;\n\nexport function MediaTrackProvider({\n client,\n children,\n active = true,\n}: MediaTrackProviderProps) {\n const runtime = useMemo(() => createMediaTrackRuntime<TweetMedia>(), []);\n\n return (\n <MediaTrackContext.Provider value={{ client }}>\n <MediaTrackRuntimeContext.Provider value={runtime}>\n <MediaTrackClientBridge client={client} active={active} />\n {children}\n </MediaTrackRuntimeContext.Provider>\n </MediaTrackContext.Provider>\n );\n}\n\nfunction MediaTrackClientBridge({\n client,\n active,\n}: {\n client: IMediaTrackClient;\n active: boolean;\n}) {\n const runtime = useContext(MediaTrackRuntimeContext);\n useEffect(() => {\n if (!runtime || !active) return;\n runtime.connect();\n const basic = client.subscribeTweetMedia({\n callback: (media) => runtime.publish(\"x-monitor-basic\", media),\n });\n const token = client.subscribeTweetMediaToken({\n callback: (media) => runtime.publish(\"x-monitor-token\", media),\n });\n return () => {\n basic.unsubscribe();\n token.unsubscribe();\n runtime.disconnect();\n client.disconnect();\n };\n }, [active, client, runtime]);\n return null;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liberfi.io/ui-media-track",
3
- "version": "0.1.286",
3
+ "version": "0.1.288",
4
4
  "description": "Media Track for Liberfi React SDK",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -28,11 +28,11 @@
28
28
  "dependencies": {
29
29
  "@chainstream-io/centrifuge": "^1.0.0",
30
30
  "tailwind-variants": "^3.1.1",
31
- "@liberfi.io/hooks": "0.1.283",
32
- "@liberfi.io/i18n": "0.1.288",
33
- "@liberfi.io/types": "0.4.91",
34
- "@liberfi.io/ui": "0.3.91",
35
- "@liberfi.io/utils": "0.2.90"
31
+ "@liberfi.io/hooks": "0.1.285",
32
+ "@liberfi.io/types": "0.4.93",
33
+ "@liberfi.io/ui": "0.3.93",
34
+ "@liberfi.io/utils": "0.2.92",
35
+ "@liberfi.io/i18n": "0.1.290"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@tanstack/react-query": "^5.90.2",
@@ -46,7 +46,7 @@
46
46
  "ts-jest": "^29.4.6",
47
47
  "tsup": "^8.5.0",
48
48
  "typescript": "^5.9.2",
49
- "tsconfig": "0.1.274"
49
+ "tsconfig": "0.1.276"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "@tanstack/react-query": "^5.90.2",