| Index: lib/filterStorage.js | 
| =================================================================== | 
| --- a/lib/filterStorage.js | 
| +++ b/lib/filterStorage.js | 
| @@ -193,19 +193,23 @@ | 
| /** | 
| * Replaces the list of filters in a subscription with a new list. | 
| * @param {Subscription} subscription The subscription to be updated. | 
| * @param {Array.<Filter>} filters The new list of filters. | 
| */ | 
| updateSubscriptionFilters(subscription, filters) | 
| { | 
| disconnectSubscriptionFilters(subscription); | 
| + | 
| let oldFilters = subscription.filters; | 
| -    subscription.filters = filters; | 
| -    connectSubscriptionFilters(subscription); | 
| +    subscription.filters = []; | 
| +    for (let filter of filters) | 
| +      subscription.filters.push(filter.text); | 
| + | 
| +    connectSubscriptionFilters(subscription, filters); | 
| filterNotifier.emit("subscription.updated", subscription, oldFilters); | 
| } | 
|  | 
| /** | 
| * Adds a user-defined filter to the storage. | 
| * @param {Filter} filter | 
| * @param {?SpecialSubscription} [subscription] The subscription that the | 
| *   filter should be added to. | 
| @@ -234,17 +238,17 @@ | 
| this.addSubscription(subscription); | 
| return; | 
| } | 
|  | 
| if (typeof position == "undefined") | 
| position = subscription.filters.length; | 
|  | 
| filter.addSubscription(subscription); | 
| -    subscription.filters.splice(position, 0, filter); | 
| +    subscription.filters.splice(position, 0, filter.text); | 
| filterNotifier.emit("filter.added", filter, subscription, position); | 
| } | 
|  | 
| /** | 
| * Removes a user-defined filter from the storage. | 
| * @param {Filter} filter | 
| * @param {?SpecialSubscription} [subscription] The subscription that the | 
| *   filter should be removed from. If not specified, the filter will be | 
| @@ -263,31 +267,31 @@ | 
| if (currentSubscription instanceof SpecialSubscription) | 
| { | 
| let positions = []; | 
| if (typeof position == "undefined") | 
| { | 
| let index = -1; | 
| do | 
| { | 
| -            index = currentSubscription.filters.indexOf(filter, index + 1); | 
| +            index = currentSubscription.filters.indexOf(filter.text, index + 1); | 
| if (index >= 0) | 
| positions.push(index); | 
| } while (index >= 0); | 
| } | 
| else | 
| positions.push(position); | 
|  | 
| for (let j = positions.length - 1; j >= 0; j--) | 
| { | 
| let currentPosition = positions[j]; | 
| -          if (currentSubscription.filters[currentPosition] == filter) | 
| +          if (currentSubscription.filters[currentPosition] == filter.text) | 
| { | 
| currentSubscription.filters.splice(currentPosition, 1); | 
| -            if (currentSubscription.filters.indexOf(filter) < 0) | 
| +            if (currentSubscription.filters.indexOf(filter.text) < 0) | 
| filter.removeSubscription(currentSubscription); | 
| filterNotifier.emit("filter.removed", filter, currentSubscription, | 
| currentPosition); | 
| } | 
| } | 
| } | 
| } | 
| } | 
| @@ -298,28 +302,28 @@ | 
| * @param {SpecialSubscription} subscription The subscription where the | 
| *   filter is located. | 
| * @param {number} oldPosition The current position of the filter. | 
| * @param {number} newPosition The new position of the filter. | 
| */ | 
| moveFilter(filter, subscription, oldPosition, newPosition) | 
| { | 
| if (!(subscription instanceof SpecialSubscription) || | 
| -        subscription.filters[oldPosition] != filter) | 
| +        subscription.filters[oldPosition] != filter.text) | 
| { | 
| return; | 
| } | 
|  | 
| newPosition = Math.min(Math.max(newPosition, 0), | 
| subscription.filters.length - 1); | 
| if (oldPosition == newPosition) | 
| return; | 
|  | 
| subscription.filters.splice(oldPosition, 1); | 
| -    subscription.filters.splice(newPosition, 0, filter); | 
| +    subscription.filters.splice(newPosition, 0, filter.text); | 
| filterNotifier.emit("filter.moved", filter, subscription, oldPosition, | 
| newPosition); | 
| } | 
|  | 
| /** | 
| * Increases the hit count for a filter by one. | 
| * @param {Filter} filter | 
| */ | 
| @@ -492,22 +496,22 @@ | 
| { | 
| yield* subscription.serialize(); | 
| yield* subscription.serializeFilters(); | 
| } | 
|  | 
| // Save filter data | 
| for (let subscription of subscriptions) | 
| { | 
| -      for (let filter of subscription.filters) | 
| +      for (let text of subscription.filters) | 
| { | 
| -        if (!saved.has(filter.text)) | 
| +        if (!saved.has(text)) | 
| { | 
| -          yield* filter.serialize(); | 
| -          saved.add(filter.text); | 
| +          yield* Filter.fromText(text).serialize(); | 
| +          saved.add(text); | 
| } | 
| } | 
| } | 
| } | 
|  | 
| /** | 
| * Saves all subscriptions back to disk. | 
| * @returns {Promise} A promise resolved or rejected when saving is complete. | 
| @@ -642,31 +646,53 @@ | 
| let filterStorage = new FilterStorage(); | 
|  | 
| exports.filterStorage = filterStorage; | 
|  | 
| /** | 
| * Connects a subscription to its filters without any notifications. | 
| * @param {Subscription} subscription The subscription that should be | 
| *   connected to its filters. | 
| + * @param {?Array.<Filter>} [filters] A list of filters to which the | 
| + *   subscription should be connected. If this is not given, the subscription | 
| + *   is connected to its own filters. | 
| */ | 
| -function connectSubscriptionFilters(subscription) | 
| +function connectSubscriptionFilters(subscription, filters) | 
| { | 
| if (!filterStorage.knownSubscriptions.has(subscription.url)) | 
| return; | 
|  | 
| -  for (let filter of subscription.filters) | 
| -    filter.addSubscription(subscription); | 
| +  if (filters) | 
| +  { | 
| +    for (let filter of filters) | 
| +      filter.addSubscription(subscription); | 
| +  } | 
| +  else | 
| +  { | 
| +    for (let text of subscription.filters) | 
| +      Filter.fromText(text).addSubscription(subscription); | 
| +  } | 
| } | 
|  | 
| /** | 
| * Disconnects a subscription from its filters without any notifications. | 
| * @param {Subscription} subscription The subscription that should be | 
| *   disconnected from its filters. | 
| + * @param {?Array.<Filter>} [filters] A list of filters from which the | 
| + *   subscription should be disconnected. If this is not given, the | 
| + *   subscription is disconnected from its own filters. | 
| */ | 
| -function disconnectSubscriptionFilters(subscription) | 
| +function disconnectSubscriptionFilters(subscription, filters) | 
| { | 
| if (!filterStorage.knownSubscriptions.has(subscription.url)) | 
| return; | 
|  | 
| -  for (let filter of subscription.filters) | 
| -    filter.removeSubscription(subscription); | 
| +  if (filters) | 
| +  { | 
| +    for (let filter of filters) | 
| +      filter.removeSubscription(subscription); | 
| +  } | 
| +  else | 
| +  { | 
| +    for (let text of subscription.filters) | 
| +      Filter.fromText(text).removeSubscription(subscription); | 
| +  } | 
| } | 
|  |