Compare commits

...

2 Commits

5 changed files with 168 additions and 152 deletions

View File

@ -167,7 +167,8 @@
information hidden to make reading information hidden to make reading
messages easier. messages easier.
<ul> <ul>
<li>Tap on the pound sign to see the <li>Tap on the <i class="bi
bi-clock"></i> clock to see the
date and time of the message.</li> date and time of the message.</li>
<li>Tap again to hide the popup.</li> <li>Tap again to hide the popup.</li>
<li>Long chat messages are scrollable. <li>Long chat messages are scrollable.

View File

@ -63,7 +63,7 @@ th, td {
} }
.message-mobile-date-time { .message-mobile-date-time {
width: 1em; width: 2em;
} }
.message-from-user { .message-from-user {

View File

@ -103,7 +103,8 @@ function processFragment() {
async function saveToDatabase(filename: string, xml: string) { async function saveToDatabase(filename: string, xml: string) {
db.entries db.entries
.put({ filename, backupData: xml }) .put({ filename, backupData: xml })
.catch(err => displayFatalError('Saving Failed', err)); .then(_ => toggleLoadPrevious(true))
.catch(err => console.error('Saving Failed', err));
} }
function displayBackup(xsltProcessor: XSLTProcessor, filename: string, xmlText: string): boolean { function displayBackup(xsltProcessor: XSLTProcessor, filename: string, xmlText: string): boolean {
@ -136,7 +137,29 @@ function displayBackup(xsltProcessor: XSLTProcessor, filename: string, xmlText:
} }
} }
function initEvents() { function toggleLoadPrevious(toggle: boolean) {
ui.loadPreviousButtons.forEach(btn => {
if (toggle) {
btn.classList.remove('disabled');
} else {
btn.classList.add('disabled');
}
});
}
async function initEvents() {
db.entries.count()
.then(count => {
if (count < 1) {
toggleLoadPrevious(false);
}
})
.catch(err => {
//Something wrong with db access, disable buttons anyway.
console.error(err);
toggleLoadPrevious(false);
});
ui.loadPreviousButtons.forEach(button => button.addEventListener('click', async () => { ui.loadPreviousButtons.forEach(button => button.addEventListener('click', async () => {
await populateSavedBackups(); await populateSavedBackups();
})); }));
@ -190,15 +213,7 @@ async function populateSavedBackups() {
} }
window.addEventListener('DOMContentLoaded', async () => { window.addEventListener('DOMContentLoaded', async () => {
window.addEventListener('resize', () => { await initEvents();
if (window.innerWidth <= 500) {
ui.chatDisplay.querySelector('table')?.classList.add('table-sm');
} else {
ui.chatDisplay.querySelector('table')?.classList.remove('table-sm');
}
});
initEvents();
showLoadingIndicator(false); showLoadingIndicator(false);
showApplication(true); showApplication(true);
}); });

View File

@ -8,9 +8,9 @@ export const chatDisplay: HTMLElement = document.getElementById('chat-display')!
export const fileSelector: HTMLInputElement = document.getElementById('backup-file')! as HTMLInputElement; export const fileSelector: HTMLInputElement = document.getElementById('backup-file')! as HTMLInputElement;
export const savedBackups: HTMLSelectElement = document.getElementById('saved-backups')! as HTMLSelectElement; export const savedBackups: HTMLSelectElement = document.getElementById('saved-backups')! as HTMLSelectElement;
export const viewNewButtons = export const viewNewButtons =
document.querySelectorAll('#unloaded-view-new-button, #loaded-view-new-button'); <NodeListOf<HTMLElement>>document.querySelectorAll('#unloaded-view-new-button, #loaded-view-new-button');
export const loadPreviousButtons = export const loadPreviousButtons =
document.querySelectorAll('#unloaded-load-previous-button, #loaded-load-previous-button'); <NodeListOf<HTMLElement>>document.querySelectorAll('#unloaded-load-previous-button, #loaded-load-previous-button');
export const previousBackupsList: HTMLDivElement = document.getElementById('previous-backups-list')! as HTMLDivElement; export const previousBackupsList: HTMLDivElement = document.getElementById('previous-backups-list')! as HTMLDivElement;
export const noFileLoadedControls: HTMLDivElement = document.getElementById('no-file-loaded-controls')! as HTMLDivElement; export const noFileLoadedControls: HTMLDivElement = document.getElementById('no-file-loaded-controls')! as HTMLDivElement;
export const fileLoadedControls: HTMLDivElement = document.getElementById('file-loaded-controls')! as HTMLDivElement; export const fileLoadedControls: HTMLDivElement = document.getElementById('file-loaded-controls')! as HTMLDivElement;

View File

@ -1,137 +1,137 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- <!--
This XSLT file is based on the default XSL stylesheet generated by MSN This XSLT file is based on the default XSL stylesheet generated by MSN
Messenger, and unlike the rest of the application, is probably(?) not Messenger, and unlike the rest of the application, is probably(?) not
covered under the AGPL. covered under the AGPL.
The file was originally retrieved from this project: The file was originally retrieved from this project:
https://github.com/jerecui/MSNChatHistoryCombiner https://github.com/jerecui/MSNChatHistoryCombiner
--> -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- localized strings --> <!-- localized strings -->
<xsl:variable name='ColumnHeader_Date'>Date</xsl:variable> <xsl:variable name='ColumnHeader_Date'>Date</xsl:variable>
<xsl:variable name='ColumnHeader_Time'>Time</xsl:variable> <xsl:variable name='ColumnHeader_Time'>Time</xsl:variable>
<xsl:variable name='ColumnHeader_From'>From</xsl:variable> <xsl:variable name='ColumnHeader_From'>From</xsl:variable>
<xsl:variable name='ColumnHeader_Message'>Message</xsl:variable> <xsl:variable name='ColumnHeader_Message'>Message</xsl:variable>
<!-- variables --> <!-- variables -->
<xsl:variable name='UseZebraStripe'>1</xsl:variable> <xsl:variable name='UseZebraStripe'>1</xsl:variable>
<xsl:variable name='ZebraStripeStyle'>background-color:#e0edff</xsl:variable> <xsl:variable name='ZebraStripeStyle'>background-color:#e0edff</xsl:variable>
<xsl:variable name='MostRecentSessionFirst'>0</xsl:variable> <xsl:variable name='MostRecentSessionFirst'>0</xsl:variable>
<xsl:template match="Log"> <xsl:template match="Log">
<table id='BodyTable' class="table"> <table id='BodyTable' class="table">
<thead> <thead>
<tr> <tr>
<th class="d-lg-none message-mobile-date-time"> <th class="d-lg-none message-mobile-date-time">
<!-- for mobile date/time --> <!-- for mobile date/time -->
</th> </th>
<th class="d-none d-lg-table-cell"> <th class="d-none d-lg-table-cell">
<xsl:value-of select="$ColumnHeader_Date"/> <xsl:value-of select="$ColumnHeader_Date"/>
</th> </th>
<th class="d-none d-lg-table-cell"> <th class="d-none d-lg-table-cell">
<xsl:value-of select="$ColumnHeader_Time"/> <xsl:value-of select="$ColumnHeader_Time"/>
</th> </th>
<th class="message-from-user"> <th class="message-from-user">
<xsl:value-of select="$ColumnHeader_From"/> <xsl:value-of select="$ColumnHeader_From"/>
</th> </th>
<th> <th>
<xsl:value-of select="$ColumnHeader_Message"/> <xsl:value-of select="$ColumnHeader_Message"/>
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody class="table-group-divider"> <tbody class="table-group-divider">
<xsl:choose> <xsl:choose>
<!-- newest session first --> <!-- newest session first -->
<xsl:when test="$MostRecentSessionFirst = 1"> <xsl:when test="$MostRecentSessionFirst = 1">
<xsl:apply-templates> <xsl:apply-templates>
<xsl:sort select='@SessionID' order='descending' data-type='number'/> <xsl:sort select='@SessionID' order='descending' data-type='number'/>
<xsl:sort select='@DateTime' order='ascending'/> <xsl:sort select='@DateTime' order='ascending'/>
</xsl:apply-templates> </xsl:apply-templates>
</xsl:when> </xsl:when>
<!-- oldest session first --> <!-- oldest session first -->
<xsl:otherwise> <xsl:otherwise>
<xsl:apply-templates> <xsl:apply-templates>
<xsl:sort select='@SessionID' order='ascending' data-type='number'/> <xsl:sort select='@SessionID' order='ascending' data-type='number'/>
<xsl:sort select='@DateTime' order='ascending'/> <xsl:sort select='@DateTime' order='ascending'/>
</xsl:apply-templates> </xsl:apply-templates>
</xsl:otherwise> </xsl:otherwise>
</xsl:choose> </xsl:choose>
</tbody> </tbody>
</table> </table>
</xsl:template> </xsl:template>
<xsl:template match="Message"> <xsl:template match="Message">
<tr> <tr>
<xsl:call-template name="CommonMessageProcessing" /> <xsl:call-template name="CommonMessageProcessing" />
<td class="message-from-user"><xsl:apply-templates select="From/User"/> </td> <td class="message-from-user"><xsl:apply-templates select="From/User"/> </td>
<td class="message-content"> <td class="message-content">
<div class="overflow-auto"> <div class="overflow-auto">
<xsl:value-of select="Text"/> <xsl:value-of select="Text"/>
</div> </div>
</td> </td>
</tr> </tr>
</xsl:template> </xsl:template>
<xsl:template match="Invitation|InvitationResponse|Join|Leave"> <xsl:template match="Invitation|InvitationResponse|Join|Leave">
<tr> <tr>
<xsl:call-template name="CommonMessageProcessing" /> <xsl:call-template name="CommonMessageProcessing" />
<td> <td>
<span> <span>
<xsl:value-of select="Text"/> <xsl:value-of select="Text"/>
</span> </span>
</td> </td>
</tr> </tr>
</xsl:template> </xsl:template>
<xsl:template match="From/User"> <xsl:template match="From/User">
<a class="info-popover" href="#" tabindex="0" <a class="info-popover" href="javascript:void(0);" tabindex="0"
data-bs-trigger="focus" data-bs-trigger="focus"
data-bs-container="body" data-bs-toggle="popover" data-bs-container="body" data-bs-toggle="popover"
data-bs-placement="bottom" data-bs-title="Username"> data-bs-placement="bottom" data-bs-title="Username">
<xsl:attribute name="data-bs-content"> <xsl:attribute name="data-bs-content">
<xsl:value-of select="@FriendlyName"/> <xsl:value-of select="@FriendlyName"/>
</xsl:attribute> </xsl:attribute>
<xsl:value-of select="@FriendlyName"/> <xsl:value-of select="@FriendlyName"/>
</a> </a>
</xsl:template> </xsl:template>
<xsl:template name="CommonMessageProcessing"> <xsl:template name="CommonMessageProcessing">
<!-- zebra-stripe the sessions --> <!-- zebra-stripe the sessions -->
<xsl:if test="$UseZebraStripe = 1"> <xsl:if test="$UseZebraStripe = 1">
<xsl:if test="(@SessionID mod 2) = 1"> <xsl:if test="(@SessionID mod 2) = 1">
<xsl:attribute name="style"> <xsl:attribute name="style">
<xsl:value-of select="$ZebraStripeStyle"/> <xsl:value-of select="$ZebraStripeStyle"/>
</xsl:attribute> </xsl:attribute>
</xsl:if> </xsl:if>
</xsl:if> </xsl:if>
<!-- mobile shows a popover span for date/time --> <!-- mobile shows a popover span for date/time -->
<td class="d-lg-none message-mobile-date-time"> <td class="d-lg-none message-mobile-date-time">
<a class="info-popover" href="#" tabindex="0" <a class="info-popover" href="javascript:void(0);" tabindex="0"
data-bs-trigger="focus" data-bs-trigger="focus"
data-bs-container="body" data-bs-toggle="popover" data-bs-container="body" data-bs-toggle="popover"
data-bs-placement="right" data-bs-title="Date/Time"> data-bs-placement="right" data-bs-title="Date/Time">
<xsl:attribute name="data-bs-content"> <xsl:attribute name="data-bs-content">
<xsl:value-of select="@Date"/>&#160;<xsl:value-of select="@Time"/> <xsl:value-of select="@Date"/>&#160;<xsl:value-of select="@Time"/>
</xsl:attribute> </xsl:attribute>
# <i class="bi bi-clock"></i>
</a> </a>
</td> </td>
<td class="d-none d-lg-table-cell message-date"> <xsl:value-of select="@Date"/> </td> <td class="d-none d-lg-table-cell message-date"> <xsl:value-of select="@Date"/> </td>
<td class="d-none d-lg-table-cell message-time"> <xsl:value-of select="@Time"/> </td> <td class="d-none d-lg-table-cell message-time"> <xsl:value-of select="@Time"/> </td>
</xsl:template> </xsl:template>
</xsl:stylesheet> </xsl:stylesheet>