-
Notifications
You must be signed in to change notification settings - Fork 354
DBUS
On linux / mac it is possible to access DBUS using https://npmjs.org/package/dbus-native.
method void org.gnome.ScreenSaver.Lock() method void org.gnome.ScreenSaver.SetActive(bool value) method void org.gnome.ScreenSaver.ShowMessage(QString summary, QString body, QString icon) method void org.gnome.ScreenSaver.SimulateUserActivity()
method void org.gnome.SettingsDaemon.MediaKeys.GrabMediaPlayerKeys(QString application, uint time)
qdbus --system org.freedesktop.UDisks /org/freedesktop/UDisks/devices/sda5 org.freedesktop.UDisks.Device.PartitionSize
import React, { useMemo, useState, useCallback } from "react"; import { SafeAreaView, View, Text, FlatList, TouchableOpacity, StyleSheet, StatusBar, } from "react-native";
// ----------------------------- // Datos de ejemplo Saufy TV // ----------------------------- const VIDEOS = [ { id: "1", titulo: "Juventud y liderazgo en Ecuador", descripcion: "Conversación sobre liderazgo juvenil, política y participación ciudadana en Ecuador.", tags: ["juventud", "liderazgo", "ecuador", "politica"], duracionMin: 42, fechaPublicacion: "2025-11-10", viewsTotales: 1250, likesTotales: 210, tipo: "podcast_largo", invitado: "Líder juvenil AIESEC", }, { id: "2", titulo: "Historias desde el pupito del mundo", descripcion: "Relatos íntimos de vida, resiliencia y sueños contados desde los buses y las calles de Quito.", tags: ["historias", "vida", "quito", "emocional"], duracionMin: 35, fechaPublicacion: "2025-11-15", viewsTotales: 890, likesTotales: 150, tipo: "podcast_largo", invitado: "Saúl Chisaguano", }, { id: "3", titulo: "Sexo, cuerpo y tabúes: hablemos sin miedo", descripcion: "Episodio sobre educación sexual, tabúes y cómo comunicarnos con responsabilidad.", tags: ["sexualidad", "cuerpo", "tabu", "educacion"], duracionMin: 55, fechaPublicacion: "2025-11-12", viewsTotales: 1670, likesTotales: 320, tipo: "podcast_largo", invitado: "Invitada especialista", }, { id: "4", titulo: "Clip: ¿Qué es ser líder en 30 segundos?", descripcion: "Clip corto sobre la esencia del liderazgo en contextos juveniles.", tags: ["liderazgo", "juventud", "clip"], duracionMin: 1, fechaPublicacion: "2025-11-16", viewsTotales: 3200, likesTotales: 680, tipo: "clip", invitado: "Líder juvenil AIESEC", }, { id: "5", titulo: "Emprender desde cero con 2 maletas", descripcion: "Historia de emprendimiento, fracasos y comenzar de nuevo con casi nada.", tags: ["emprendimiento", "historias", "motivacion"], duracionMin: 48, fechaPublicacion: "2025-11-08", viewsTotales: 980, likesTotales: 190, tipo: "podcast_largo", invitado: "Emprendedor invitado", }, { id: "6", titulo: "Clip: Un consejo para no rendirte hoy", descripcion: "Mensaje corto para quienes están a punto de rendirse con sus proyectos.", tags: ["motivacion", "clip", "vida"], duracionMin: 2, fechaPublicacion: "2025-11-17", viewsTotales: 4100, likesTotales: 910, tipo: "clip", invitado: "Saúl Chisaguano", }, ];
// Usuario simulado (luego esto se puede conectar a auth real) const USUARIO_INICIAL = { id: "user-1", nombre: "Saúl", interesesIniciales: [ "juventud", "liderazgo", "historias", "emprendimiento", "sexualidad", ], };
// ----------------------------- // Helpers // -----------------------------
function diasDesde(fechaStr) { const hoy = new Date(); const fecha = new Date(fechaStr); const diffMs = hoy.getTime() - fecha.getTime(); return Math.floor(diffMs / (1000 * 60 * 60 * 24)); }
function normalizarCampo(lista, campo) { const valores = lista.map((v) => v[campo]); const max = Math.max(...valores); const min = Math.min(...valores); if (max === min) { return {}; // todos iguales, no aporta } const resultado = {}; lista.forEach((v) => { resultado[v.id] = (v[campo] - min) / (max - min); }); return resultado; }
// ----------------------------- // Lógica de recomendación // -----------------------------
function obtenerInteresesDesdeHistorial(historial, videos) { const contadorTags = {}; historial.forEach((item) => { const video = videos.find((v) => v.id === item.idVideo); if (!video) return; video.tags.forEach((tag) => { if (!contadorTags[tag]) contadorTags[tag] = 0; contadorTags[tag] += 1; }); });
const pares = Object.entries(contadorTags); pares.sort((a, b) => b[1] - a[1]); // orden descendente return pares.slice(0, 5).map(([tag]) => tag); }
function recomendarVideos(usuario, historial, videos) { const vistos = new Set(historial.map((h) => h.idVideo)); const interesesUsuario = historial.length > 0 ? obtenerInteresesDesdeHistorial(historial, videos) : usuario.interesesIniciales;
const viewsNorm = normalizarCampo(videos, "viewsTotales"); const likesNorm = normalizarCampo(videos, "likesTotales");
const puntuados = videos.map((video) => { let score = 0;
// 1. Coincidencia con intereses
const tagsEnComun = video.tags.filter((t) =>
interesesUsuario.includes(t)
).length;
score += tagsEnComun * 3;
// 2. Popularidad
const vNorm = viewsNorm[video.id] ?? 0;
const lNorm = likesNorm[video.id] ?? 0;
score += vNorm * 2;
score += lNorm * 2;
// 3. Novedad
const dias = diasDesde(video.fechaPublicacion);
if (dias < 3) score += 5;
else if (dias < 7) score += 3;
else if (dias < 30) score += 1;
// 4. Afinidad por invitado en historial
const haVistoMismoInvitado = historial.some((h) => {
const vHist = videos.find((v) => v.id === h.idVideo);
return vHist && vHist.invitado === video.invitado;
});
if (haVistoMismoInvitado) score += 4;
// 5. Penalizar si ya visto casi completo (simulado con flag)
const r